在开发中,我们难免会遇到这样的需求,在tableView的cell上要显示一张网络图片,cell的高度要根据网络图片的高度而定。此时我们就要根据url来获取网络图片的尺寸从而来布局cell,废话不多说,首先第一种方法
//获取image的size
+ (CGSize)getImageSizeWithURL:(NSURL*)url{
if(![urlisKindOfClass:[NSURLclass]]||(url ==nil)) {
returnCGSizeZero;
}
CGFloatwidth =0.0f, height =0.0f;
UIImage *img = [[SDImageCache sharedImageCache]imageFromCacheForKey:url.absoluteString];
if(img) {
width = img.size.width;
height = img.size.height;
}else{
CGImageSourceRefimageSourceRef = CGImageSourceCreateWithURL((CFURLRef)url, NULL);
if(imageSourceRef) {
CFDictionaryRefimageProperties =CGImageSourceCopyPropertiesAtIndex(imageSourceRef,0,NULL);
if(imageProperties !=NULL) {
CFNumberRef widthNumberRef = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelWidth);
//判断设备是否为64位
#if defined(__LP64__) && __LP64__
if(widthNumberRef !=NULL) {
CFNumberGetValue(widthNumberRef, kCFNumberFloat64Type, &width);
}
CFNumberRef heightNumberRef = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelHeight);
if(heightNumberRef !=NULL) {
CFNumberGetValue(heightNumberRef, kCFNumberFloat64Type, &height);
}
#else
if(widthNumberRef !=NULL) {
CFNumberGetValue(widthNumberRef,kCFNumberFloat32Type, &width);
}
CFNumberRef heightNumberRef = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelHeight);
if(heightNumberRef !=NULL) {
CFNumberGetValue(heightNumberRef,kCFNumberFloat32Type, &height);
}
#endif
CFRelease(imageProperties);
}
CFRelease(imageSourceRef);
NSLog(@"Image dimensions: %.0f x %.0f px", width, height);
}}
returnCGSizeMake(width, height);
}
在根据url获取到图片的尺寸后,直接将size的高作为cell的高度。
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath {
CGSizeimageSize = [self getImageSizeWithURL:[NSURL URLWithString:[NSString getVedioUrl:dic[@"url"]]]];
return imageSize.height* (kScreen_Width-20) / imageSize.width+4;
}
当然这种方法有弊端,它在获取图片尺寸的时候是很耗时的操作,所以会阻碍到主线程,从而造成界面卡顿,当所有图片的尺寸都得到之后才会显示UI。有兴趣的同学可以尝试一下新建线程异步获取图片尺寸,获取到尺寸之后重新刷新tableview,这也是后面第二种方法的思路。
下面来说说第二种方法,它是根据SDWebImage来处理的。我们都知道,每个图片对应的url都是唯一的,所以我们可以创建一个可变字典将图片的url作为key值,对应的高度作为value值保存起来,加载完图片后刷新tableview就好了。
//获取网络图片的size,根据比例计算出图片在APP中的高度
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath {
CGFloat photoHeight =0;
for(NSString*url in[self.sizeDic allKeys]) {
if([url isEqualToString:dic[@"url"]]) {
photoHeight = [self.sizeDic[url] floatValue];
}
}
if(photoHeight >0) {
returnphotoHeight;
}else{
UIImageView*imageView = [[UIImageView alloc] init];
[imageViewsd_setImageWithURL:[NSURL URLWithString:dic[@"url"]]] placeholderImage:nil completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
CGFloatheight = image.size.height* (kScreen_Width-20) / image.size.width+4;
[self.sizeDic setObject:@(height) forKey:dic[@"url"]];
[self.tableView reloadData];
}];
return0;
}
}
其实第一种方法也可以新建线程异步处理,但是考虑到SDWebImage已经帮我们处理好了,此时就直接用第二种方法吧