zoukankan      html  css  js  c++  java
  • NSOperation下载图片-02

    有沙盒缓存

      1 #import "HMAppViewController.h"
      2 #import "HMApp.h"
      3 
      4 #define HMAppImageFile(url) [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[url lastPathComponent]]
      5 
      6 @interface HMAppViewController ()
      7 /**
      8  *  模型数组
      9  */
     10 @property (nonatomic, strong) NSArray *apps;
     11 
     12 /**
     13  *  存储icon的url的字典
     14  */
     15 @property (nonatomic, strong) NSMutableDictionary *operations;
     16 
     17 /**
     18  *  全局队列
     19  */
     20 @property (nonatomic, strong) NSOperationQueue *queue;
     21 
     22 /**
     23  *  存储app的图标的字典
     24  */
     25 @property (nonatomic, strong) NSMutableDictionary *images;
     26 @end
     27 
     28 @implementation HMAppViewController
     29 
     30 #pragma mark - 懒加载
     31 - (NSArray *)apps
     32 {
     33     if(!_apps)
     34     {
     35         _apps = [HMApp apps];
     36     }
     37     return _apps;
     38 }
     39 
     40 - (NSMutableDictionary *)operations
     41 {
     42     if(!_operations)
     43     {
     44         _operations = [NSMutableDictionary dictionary];
     45     }
     46     return _operations;
     47 }
     48 
     49 - (NSOperationQueue *)queue
     50 {
     51     if(!_queue)
     52     {
     53         _queue = [[NSOperationQueue alloc] init];
     54     }
     55     return _queue;
     56 }
     57 
     58 - (NSMutableDictionary *)images
     59 {
     60     if(!_images)
     61     {
     62         _images = [NSMutableDictionary dictionary];
     63     }
     64     return _images;
     65 }
     66 
     67 - (void)viewDidLoad
     68 {
     69     [super viewDidLoad];
     70     
     71 }
     72 
     73 - (void)didReceiveMemoryWarning
     74 {
     75     [super didReceiveMemoryWarning];
     76     
     77     // 移除所有的下载操作
     78     [self.queue cancelAllOperations];
     79     [self.operations removeAllObjects];
     80     
     81     // 移除所有的图片缓存
     82     [self.images removeAllObjects];
     83 }
     84 
     85 // 默认是一组
     86 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
     87 {
     88     return 1;
     89 }
     90 
     91 // 每一section有多少行
     92 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
     93 {
     94     return self.apps.count;
     95 }
     96 
     97 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
     98 {
     99     static NSString *ID = @"app";
    100     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    101     if(!cell)
    102     {
    103         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    104     }
    105     HMApp *app = self.apps[indexPath.row];
    106     cell.textLabel.text = app.name;
    107     cell.detailTextLabel.text = app.download;
    108     
    109     // 先从images缓存中取出图片url对应的UIImage
    110     // 取出url对应的图片
    111     UIImage *storageImage = self.images[app.icon];
    112     
    113     if(storageImage) // 说明图片已下载成功过(成功缓存)在内存中
    114     {
    115         cell.imageView.image = storageImage;
    116     }
    117     else
    118     {
    119         // 获取caches的路径,拼接文件路径
    120 //        NSString *file = HMAppImageFile(app.icon);
    121         
    122         // 先从沙盒中取出图片
    123         NSData *data = [NSData dataWithContentsOfFile:HMAppImageFile(app.icon)];
    124         
    125         if(data)
    126         {   // 如果沙盒中有值
    127             cell.imageView.image = [UIImage imageWithData:data];
    128         }
    129         else
    130         {   // 如果沙盒中没有值
    131             // 要么显示已下载好的图片,要么显示占位图片,防止cell的循环利用时显示其它的图片
    132             // 占位图,确保image有尺寸,更新时可以显示最新的图片
    133             cell.imageView.image = [UIImage imageNamed:@"placeholder"];
    134             
    135             [self download:app.icon indexPath:indexPath];
    136         }
    137     }
    138     
    139     return cell;
    140     
    141     // 怎么保证一图片(url)不被重复下载
    142     // 用字典解决,key-》url,value-》image
    143 }
    144 
    145 /**
    146  *  下载图片和刷新UI
    147  */
    148 - (void)download:(NSString *)imageUrl indexPath:(NSIndexPath *)indexPath
    149 {
    150     NSBlockOperation *operation = self.operations[imageUrl];
    151 //    NSInvocationOperation
    152     
    153     if(operation) return;
    154     
    155     // 解决循环强引用
    156     __weak typeof(self) appVc = self;
    157     
    158     operation = [NSBlockOperation blockOperationWithBlock:^{
    159 //        [NSThread sleepForTimeInterval:2];
    160         
    161         // 创建操作,下载app图标,下载图片是耗时的操作
    162         NSURL *url = [NSURL URLWithString:imageUrl];
    163         NSData *data = [NSData dataWithContentsOfURL:url]; // 下载图片
    164         UIImage *image = [UIImage imageWithData:data];     // data->image
    165         
    166         // 回到主线程刷新UI
    167         [[NSOperationQueue mainQueue] addOperationWithBlock:^{
    168             // 设置cell图片(在子线程中的cell有可能给循环利用了,这里设置数据不合理)
    169             //                    cell.imageView.image = image;
    170             
    171             // 字典不能存放nil(空)的
    172             if(image)
    173             {
    174                 appVc.images[imageUrl] = image;
    175                 
    176 #warning 将图片存入沙盒中
    177                 // UIImage -> NSData -> File(文件)
    178                 NSData *data = UIImagePNGRepresentation(image);
    179                 
    180                 // 获取caches的路径,拼接文件路径
    181 //                NSString *file = HMAppImageFile(imageUrl);
    182                 
    183                 [data writeToFile:HMAppImageFile(imageUrl) atomically:YES];
    184             }
    185             
    186             
    187             // 从字典中移除下载操作
    188             [appVc.operations removeObjectForKey:imageUrl];
    189             
    190             // 刷新表格(刷新cell所在的行)
    191             // 这里会调用(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    192             [appVc.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
    193         }];
    194     }];
    195     
    196     // 添加操作到队列中
    197     [self.queue addOperation:operation];
    198     
    199     // 添加到字典中(这句代码为了解决重复下载)
    200     self.operations[imageUrl] = operation;
    201 }
    202 
    203 // 用户开始拖拽表格时调用
    204 -(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
    205 {
    206     // 暂停下载
    207     [self.queue setSuspended:YES];
    208 }
    209 
    210 // 用户停止拖拽表格时调用
    211 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
    212 {
    213     // 恢复下载
    214     [self.queue setSuspended:NO];
    215 }
  • 相关阅读:
    《数据结构》第1章:绪论
    《计算机网络》第1章:计算机网络体系结构
    笔记迁移至:语雀
    最大似然估计和最大后验概率
    深度学习之最大似然估计
    k折交叉验证(matlab和python程序实现)
    matlab下打乱数组顺序
    线性回归
    梯度算法的Matlab实现
    梯度下降法
  • 原文地址:https://www.cnblogs.com/fkunlam/p/4344567.html
Copyright © 2011-2022 走看看