无沙盒缓存 1 #import "HMAppViewController.h" 2 #import "HMApp.h" 3 4 @interface HMAppViewController () 5 /** 6 * 模型数组 7 */ 8 @property (nonatomic, strong) NSArray *apps; 9 10 /** 11 * 存储icon的url的字典 12 */ 13 @property (nonatomic, strong) NSMutableDictionary *operations; 14 15 /** 16 * 全局队列 17 */ 18 @property (nonatomic, strong) NSOperationQueue *queue; 19 20 /** 21 * 存储app的图标的字典 22 */ 23 @property (nonatomic, strong) NSMutableDictionary *images; 24 @end 25 26 @implementation HMAppViewController 27 28 #pragma mark - 懒加载 29 - (NSArray *)apps 30 { 31 if(!_apps) 32 { 33 _apps = [HMApp apps]; 34 } 35 return _apps; 36 } 37 38 - (NSMutableDictionary *)operations 39 { 40 if(!_operations) 41 { 42 _operations = [NSMutableDictionary dictionary]; 43 } 44 return _operations; 45 } 46 47 - (NSOperationQueue *)queue 48 { 49 if(!_queue) 50 { 51 _queue = [[NSOperationQueue alloc] init]; 52 } 53 return _queue; 54 } 55 56 - (NSMutableDictionary *)images 57 { 58 if(!_images) 59 { 60 _images = [NSMutableDictionary dictionary]; 61 } 62 return _images; 63 } 64 65 - (void)viewDidLoad 66 { 67 [super viewDidLoad]; 68 69 } 70 71 // 默认是一组 72 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 73 { 74 return 1; 75 } 76 77 // 每一section有多少行 78 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 79 { 80 return self.apps.count; 81 } 82 83 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 84 { 85 static NSString *ID = @"app"; 86 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; 87 if(!cell) 88 { 89 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; 90 } 91 HMApp *app = self.apps[indexPath.row]; 92 cell.textLabel.text = app.name; 93 cell.detailTextLabel.text = app.download; 94 95 // 先从images缓存中取出图片url对应的UIImage 96 // 取出url对应的图片 97 UIImage *storageImage = self.images[app.icon]; 98 99 if(storageImage) // 说明图片已下载成功过(成功缓存) 100 { 101 cell.imageView.image = storageImage; 102 } 103 else 104 { 105 // 要么显示已下载好的图片,要么显示占位图片,防止cell的循环利用时显示其它的图片 106 // 占位图,确保image有尺寸,更新时可以显示最新的图片 107 cell.imageView.image = [UIImage imageNamed:@"placeholder"]; 108 109 // 取出当前图片url对应的下载操作(operation对象) 110 NSBlockOperation *operation = self.operations[app.icon]; 111 if(!operation) 112 { 113 operation = [NSBlockOperation blockOperationWithBlock:^{ 114 [NSThread sleepForTimeInterval:2]; 115 116 // 创建操作,下载app图标,下载图片是耗时的操作 117 NSURL *url = [NSURL URLWithString:app.icon]; 118 NSData *data = [NSData dataWithContentsOfURL:url]; // 下载图片 119 UIImage *image = [UIImage imageWithData:data]; // data->image 120 121 // 回到主线程刷新UI 122 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 123 // 设置cell图片(在子线程中的cell有可能给循环利用了,这里设置数据不合理) 124 // cell.imageView.image = image; 125 126 // 字典不能存放nil(空)的 127 if(image) 128 { 129 self.images[app.icon] = image; 130 } 131 132 // 从字典中移除下载操作 133 [self.operations removeObjectForKey:app.icon]; 134 135 // 刷新表格(刷新cell所在的行) 136 // 这里会调用(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 137 [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; 138 }]; 139 }]; 140 141 // 添加操作到队列中 142 [self.queue addOperation:operation]; 143 144 // 添加到字典中(这句代码为了解决重复下载) 145 self.operations[app.icon] = operation; 146 } 147 } 148 149 return cell; 150 } 151 152 @end
时间: 2024-10-11 18:44:24