Load Images in chat which is locally saved faster like whatsapp

笑着哭i 提交于 2019-12-12 03:34:36

问题


I am having a chat application.It send messages and text.Currently I am getting a problem which is speed issue of loading image from local to table cell.

First I save images in Document directory for the first time download.Then I am checking that is already existing.If yes then I fetch that image from local on background thread which makes my scroll fast but when deque methods for table is working then imageview got white background and after a moment images reflect in imageview it means image fetching from local is taking time.. . . . .

So help me I need it same as whatsapp messanger app.

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];

                        });

                    });

                }

            }

回答1:


Try to make UIImageView Category file for download the image from url and it will save the file in the cache memory of the device and when you want to load that image again than it will load that image from cache memory.

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;
}

Here you just need to call this method from your class like

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

this code is working for me




回答2:


Swift Conversion: -

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 ?? ""
}


来源:https://stackoverflow.com/questions/36354256/load-images-in-chat-which-is-locally-saved-faster-like-whatsapp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!