在聊天中加载图像,像 whatsapp 一样在本地保存得更快

Load Images in chat which is locally saved faster like whatsapp

我正在聊天 application.It 发送消息 text.Currently 我遇到一个问题,即从本地加载图像到 table 单元格的速度问题。

首先,我第一次将图像保存在文档目录中 download.Then 我正在检查它已经 existing.If 是的,然后我在后台线程上从本地获取该图像,这使得我的滚动速度很快但是当table 的双端队列方法正在工作,然后 imageview 得到白色背景,片刻之后图像反映在 imageview 中,这意味着从本地获取图像需要时间...... . . .

所以帮助我,我需要它和 whatsapp messanger 应用程序一样。

static NSString *simpleTableIdentifier = @"ZImageChatCell";

        ZImageChatCell *cell = (ZImageChatCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

        if (cell == nil)
        {
            NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"ZImageChatCell" owner:self options:nil];
            cell = [nib objectAtIndex:0];
        }
            ChatMessageModel *messagemodel = [chatArray objectAtIndex:indexPath.row];

        if([messagemodel.ismymessage boolValue])
        {


            NSData *imgdata = [Base64 decode:messagemodel.previewimage];
            UIImage *effectImage = [UIImageEffects imageByApplyingLightEffectToImage:[UIImage imageWithData:imgdata]];
            [cell.rightimageview setImage:effectImage];


            BOOL imageexist = [self checkImageExistsInLocal:messagemodel.message];
            if(imageexist)
            {

                dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
                dispatch_async(queue, ^{
                UIImage *tempimage = [self fetchImageFromLocal:messagemodel.message];
                UIImage *newimage = [APPDELEGATE imageWithImage:tempimage scaledToFillSize:CGSizeMake(175, 175)];
                    dispatch_async(dispatch_get_main_queue(), ^{

                        cell.rightimageview.image = newimage;

                    });
                });
            }
            else
            {

                if(messagemodel.message.length>0)
                {
                    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

                        UIImage * imggot = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:messagemodel.message]]];
                        UIImage *newimage = [APPDELEGATE imageWithImage:imggot scaledToFillSize:CGSizeMake(175, 175)];
                        [self saveImageLocally:imggot withUrlString:messagemodel.message];

                        dispatch_async(dispatch_get_main_queue(), ^{

                            cell.rightimageview.image = newimage;
                            [cell.rightactivityloader stopAnimating];

                        });

                    });
                }

            }

        }
        else
        {

            NSData *imgdata = [Base64 decode:messagemodel.previewimage];
            UIImage *effectImage = [UIImageEffects imageByApplyingLightEffectToImage:[UIImage imageWithData:imgdata]];
            [cell.leftimageview setImage:effectImage];


            BOOL imageexist = [self checkImageExistsInLocal:messagemodel.message];
            if(imageexist)
            {
                dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
                dispatch_async(queue, ^{
                UIImage *tempimage = [self fetchImageFromLocal:messagemodel.message];
                UIImage *newimage = [APPDELEGATE imageWithImage:tempimage scaledToFillSize:CGSizeMake(SCREEN_WIDTH, SCREEN_WIDTH)];
                    dispatch_async(dispatch_get_main_queue(), ^{

                        cell.leftimageview.image = newimage;

                    });
                });
            }
            else
            {


                if(messagemodel.message.length>0)
                {
                    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

                        UIImage * imggot = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:messagemodel.message]]];
                        UIImage *newimage = [APPDELEGATE imageWithImage:imggot scaledToFillSize:CGSizeMake(175, 175)];
                        [self saveImageLocally:imggot withUrlString:messagemodel.message];

                        dispatch_async(dispatch_get_main_queue(), ^{

                            cell.leftimageview.image = newimage;
                            [cell.leftactivityloader stopAnimating];

                        });

                    });

                }

            }

尝试创建用于从 url 下载图像的 UIImageView 类别文件,它会将文件保存在设备的缓存内存中,当您想要再次加载该图像时,它将从中加载该图像高速缓存。

UIImageView+Download.h

-(void)downloadFromURL:(NSString *)url withPlaceholder:(UIImage *)placehold;

UIImageView+Download.m

-(void)downloadFromURL:(NSString *)url withPlaceholder:(UIImage *)placehold
{
    if (placehold) {
        [self setImage:placehold];
    }
    if (url) {

        //
        if ([url rangeOfString:@"/Caches/"].location != NSNotFound) {
            NSData *imageData=[NSData dataWithContentsOfFile:url];
            UIImage* image = [[UIImage alloc] initWithData:imageData];
            if (image) {
                [self setImage:image];
                [self setNeedsLayout];
            }
            return;
        }

        NSString *strImgName = [[[url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] componentsSeparatedByString:@"/"] lastObject];

        NSString *imagePath = [NSString stringWithFormat:@"%@/%@",[self applicationCacheDirectoryString],strImgName];

        NSFileManager *fileManager = [NSFileManager defaultManager];

        NSString *aURL=[url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

        if ([fileManager fileExistsAtPath:imagePath]==NO)
        {
            dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
            dispatch_async(queue, ^(void) {

                NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:aURL]];
                [imageData writeToFile:imagePath atomically:YES];

                UIImage* image = [[UIImage alloc] initWithData:imageData];
                if (image) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [self setImage:image];
                        [self setNeedsLayout];

                    });
                }
            });
        }
        else{
            NSData *imageData=[NSData dataWithContentsOfFile:imagePath];
            UIImage* image = [[UIImage alloc] initWithData:imageData];
            if (image) {
                [self setImage:image];
                [self setNeedsLayout];
            }
        }
    }
}

- (NSString *)applicationCacheDirectoryString
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cacheDirectory = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
    return cacheDirectory;
}

在这里你只需要从你的class中调用这个方法就像

[cell.imageView downloadFromURL:YOUR_IMAGE_URL withPlaceholder:PLACEHOLDER_IMAGE];

这段代码对我有用

Swift 转换:-

func download(fromURL url: String, withPlaceholder placeholder: UIImage?) {
    if placeholder != nil{
        image = placeholder!
    }
    if url != "" {
        if ((url as NSString).range(of: "/Caches/")).location != NSNotFound {
            if let img = UIImage(contentsOfFile: url){
                self.image = img
                setNeedsLayout()
            }
            return
        }

        let str: String = (url as NSString).addingPercentEscapes(using: 4)!//NSUTF8StringEncoding
        let strImg = str.components(separatedBy: "/").last!
        let imagePath = "\(applicationCacheDirectoryString())/\(strImg)"
        let fileManager = FileManager.default
        let aURL = (url as NSString).addingPercentEscapes(using: 4)!

        if fileManager.fileExists(atPath: imagePath) == false{
            let queue = DispatchQueue.global(qos: .default)
            queue.async(execute: {(_: Void) -> Void in

                do{
                    let imageData = try Data(contentsOf: URL(string: aURL)!)
                    do{
                        let url = URL(fileURLWithPath: imagePath)
                        try imageData.write(to: url, options: .atomic)
                        if let img = UIImage(data: imageData){
                            DispatchQueue.main.async(execute: {() -> Void in
                                self.image = img
                                self.setNeedsLayout()
                            })
                        }
                    }catch{
                        print("Not able to save image in cache directory from url:\(aURL)")
                    }
                }catch{
                    print("Not able to convert into Data from url:\(aURL)")
                }
            })
        }else{
            if let img = UIImage(contentsOfFile: imagePath){
                self.image = img
                setNeedsLayout()
            }
        }
    }
}

func applicationCacheDirectoryString() -> String {
    let paths = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true)
    let cacheDirectory: String? = (paths.count > 0) ? paths[0] : nil
    return cacheDirectory ?? ""
}