場景:需要加載很多張高清的圖片,列表顯示
方案一:使用獲取圖像屬性的方式來獲取
1、寫一個空的可變字典用來存高度值
根據 indexPath 生成 字符串 來用作key, 高度作為value,這為下面獲取高度打下基礎
2、從內存中查看有無緩存圖片,有的話直接用圖片的高度,沒有的話先默認一個高度
3、循環獲取圖像屬性獲取高度
注意這里獲取高度是耗時操作,使用 group 處理,待所有圖片獲取完高度即可刷新一下頁面
具體實現,參考下面的代碼
-(CGFloat)getimageHWithURLStr:(NSString*)imageStr withW:(CGFloat)imageW{ CGFloat itemBigImageH = WIN_WIDTH; if (imageStr == nil) { return itemBigImageH; } NSMutableString *imageURL = imageStr.mutableCopy; CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)[NSURL URLWithString:imageURL], NULL); if (source) { NSDictionary* imageHeader = (__bridge NSDictionary*) CGImageSourceCopyPropertiesAtIndex(source, 0, NULL); if (imageHeader != NULL) { itemBigImageH = [[imageHeader objectForKey:@"PixelHeight"] floatValue]/[[imageHeader objectForKey:@"PixelWidth"] floatValue] * imageW; } // 必須釋放 這個值一定不能為 NULL CFRelease(source); source = nil; } return itemBigImageH; }
for (int i = 0; i< _mTabData.count; i++) { NSArray *itemArr = V(_mTabData[i],@"item"); for (int j = 0; j <itemArr.count ; j++) { if ([V(itemArr[j],@"type") isEqualToString:@"images"]) { NSIndexPath *indexPath = [NSIndexPath indexPathForRow:j inSection:i]; NSString *str = [NSString stringWithFormat:@"%@_%@",@(indexPath.section),@(indexPath.row)]; // 默認高度 查看內存里是否有,有的就用內存的 NSLog(@"默認高度2-----%@---",str); UIImage *image = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:[NSString stringWithFormat:@"%@",V(itemArr[j],@"image")]]; if (image) { CGFloat iamgeWS = image.size.width / (WIN_WIDTH - 40); CGFloat iamgeHS = image.size.height / iamgeWS; [self.imageHeightArray setObject:[NSString stringWithFormat:@"%.2f",iamgeHS+6] forKey:str]; }else{ [self.imageHeightArray setObject:[NSString stringWithFormat:@"%.2f",WIN_WIDTH - 40+6] forKey:str]; } } } }
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.001 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ dispatch_group_t group = dispatch_group_create(); for (int i = 0; i< _mTabData.count; i++) { NSArray *itemArr = V(_mTabData[i],@"item"); for (int j = 0; j <itemArr.count ; j++) { if ([V(itemArr[j],@"type") isEqualToString:@"images"]) { dispatch_group_enter(group); NSIndexPath *indexPath = [NSIndexPath indexPathForRow:j inSection:i]; NSString *str = [NSString stringWithFormat:@"%@_%@",@(indexPath.section),@(indexPath.row)]; dispatch_async(dispatch_get_global_queue(0, 0), ^{ // 處理耗時操作的代碼塊... [self.imageHeightArray setObject:[NSString stringWithFormat:@"%.2f",[self getimageHWithURLStr:V(itemArr[j],@"image") withW:WIN_WIDTH - 40]+6] forKey:str]; //通知主線程刷新 dispatch_async(dispatch_get_main_queue(), ^{ // [self danhangShuaXinWith:indexPath]; // 主線程刷新i //回調或者說是通知主線程刷新, dispatch_group_leave(group); }); }); } } } dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"獲取完所有圖高度刷新------"); [_tableView reloadData]; }); }); });
方案二:使用SDWebImage里面的方法進行加載,然后拿到圖片尺寸
1、同樣的道理,首先也是要看緩存,有緩存用緩存
2、沒有緩存直接使用sd加載,加載后使用通知的形式通知頁面tableView的單行刷新
- (void)setUIWithImageStr:(NSString*)imagestr withIndexPath:(NSIndexPath*)indexPath{ WS _image = imagestr; if (imagestr == nil || [imagestr isEqualToString:@""]) { return; } UIImage *image = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:[NSString stringWithFormat:@"%@",imagestr]]; if (image) { CGFloat iamgeWS = image.size.width / (WIN_WIDTH); self.CellH = image.size.height / iamgeWS + 12.0; [self setupImageConstraninsWithImage:image]; }else{ weakSelf.CellH = WIN_WIDTH; [_vHeadPortraitImage setImageWithPureURLStr:imagestr completion:^(UIImage *image) { CGFloat iamgeWS = image.size.width / (WIN_WIDTH); weakSelf.CellH = image.size.height / iamgeWS + 12.0; [weakSelf setupImageConstraninsWithImage:image]; NSDictionary *dic = @{@"row":@(indexPath.row),@"section":@(indexPath.section),@"height":[NSString stringWithFormat:@"%.2f",(float)weakSelf.CellH]}; NSNotification *loadImageEnd = [[NSNotification alloc]initWithName:@"shuaXinImageCell" object:nil userInfo:dic]; [[NSNotificationCenter defaultCenter] postNotification:loadImageEnd]; }]; } }
- (void) shuaXinGoodsCell:(NSNotification *)notification { // 這里是加載后的通知 // NSLog(@"------notification---%@--",notification.userInfo); NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[notification.userInfo[@"row"] integerValue] inSection:[notification.userInfo[@"section"] integerValue]]; NSString *str = [NSString stringWithFormat:@"%@_%@",@(indexPath.section),@(indexPath.row)]; [self.imageHeightArray setObject:notification.userInfo[@"height"] forKey:str]; if (_mTabData.count != 0) { if (_mTabData.count > indexPath.section ) { NSArray *arr = V(_mTabData[indexPath.section],@"item"); if ([arr isKindOfClass:[NSArray class]]) { if (arr.count > indexPath.row) { [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; } } } } }
方案對比:方案一可以在獲取所有圖片高度后就可以做一些操作,比如滾動到某一行,方案二則不能