问题
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