iOS 多线程编程<十三、NSOperation图片下载,SDWebImage底层实现原理>

NSOperation图片下载,SDWebImage底层实现原理

废话不多说,直接上代码:

//
//  ViewController.m
//  DownLoadImage
//
//  Created by fe on 2016/10/21.
//  Copyright © 2016年 fe. All rights reserved.
//

#import "ViewController.h"
#import "DownloadModel.h"
@interface ViewController ()
@property (nonatomic,strong) NSArray *sourceArray;//数据源数组
@property (nonatomic,strong) NSMutableDictionary *bufferMemonry;//图片内存缓存
@property (nonatomic,strong) NSOperationQueue *operationQueue;//下载图片的队列
@property (nonatomic,strong) NSMutableDictionary *operationMemonry;//操作缓存,避免重复添加操作
@end

@implementation ViewController
- (NSArray *)sourceArray
{
    if (!_sourceArray) {
        NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"SourceList.plist" ofType:nil];
        NSArray *dicArray = [NSArray arrayWithContentsOfFile:plistPath];
        NSMutableArray *objectArray = [NSMutableArray array];
        for (NSDictionary *dic in dicArray) {
            DownloadModel *sourceModel = [DownloadModel downloadModelWithDic:dic];
            [objectArray addObject:sourceModel];
        }
        _sourceArray = objectArray;
    }
    return _sourceArray;
}
- (NSOperationQueue *)operationQueue
{
    if (!_operationQueue) {
        _operationQueue = [[NSOperationQueue alloc] init];
        _operationQueue.maxConcurrentOperationCount = 5;
    }
    return _operationQueue;
}
//懒加载方式创建内存缓存字典
- (NSMutableDictionary *)bufferMemonry
{
    if (!_bufferMemonry) {
        _bufferMemonry = [[NSMutableDictionary alloc] init];
    }
    return _bufferMemonry;
}
- (NSMutableDictionary *)operationMemonry
{
    if (!_operationMemonry) {
        _operationMemonry = [[NSMutableDictionary alloc] init];
    }
    return _operationMemonry;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.sourceArray.count;
}
/*
 要显示图片的时候,首先去内存中查看是否存在,如果存在,直接拿来用,
 如果不存在,去沙河里面找,如果沙河里面存在,直接拿来用,并且保存一份到内存。
 如果沙河里面不存在,下载图片,并且保存一份到内存,再保存一份到沙河。
 */
/*
 Documents:存在该文件夹下的数据会备份,不能把下载的文件存放在该文件夹下,
           如果把下载的文件存放在该文件夹下,苹果会拒绝你的产品上架
 Library:
     cache:用于保存下载的文件
     perference:存储偏好设置,和一些设备信息
 tmp:临时文件夹
 */
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *reuseIdentifier = @"downloadImage";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
    DownloadModel *sourceModel = self.sourceArray[indexPath.row];
    //先判断缓存中是否已经有这张图片
    UIImage *image = [self.bufferMemonry objectForKey:sourceModel.icon];
     if (image)
     {
         cell.imageView.image = [self.bufferMemonry objectForKey:sourceModel.icon];
     }else//如果缓存中没有,去沙河中看看是否存在
     {
         //获取cache路径
         NSString *cache = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
         //获取图片后缀名
         NSString *imagePath = [sourceModel.icon lastPathComponent];
         //拼接全路径
         NSString *fullPath = [cache stringByAppendingPathComponent:imagePath];
         NSData *data = [NSData dataWithContentsOfFile:fullPath];
         UIImage *image =[UIImage imageWithData:data];
         if (image)
         {
             cell.imageView.image = image;
             [self.bufferMemonry setObject:image forKey:sourceModel.icon];
         }else//如果缓存和沙河中都没有,则从服务端下载图片
         {
             //下载之前先判断操作队列里是否已经存在操作任务,如果不存在再添加任务
             NSOperation *operation = self.operationMemonry[sourceModel.icon];
             if (operation == nil) {
                 NSBlockOperation *download = [NSBlockOperation blockOperationWithBlock:^{
                     NSURL *url = [NSURL URLWithString:sourceModel.icon];
                     NSData *imageData = [NSData dataWithContentsOfURL:url];
                     if (imageData == nil) {
                         [self.operationMemonry removeObjectForKey:sourceModel.icon];
                         return ;
                     }
                     UIImage *image = [UIImage imageWithData:imageData];
                     //如果图片存在把图片写入缓存,保存到沙河
                     if (image)
                     {
                         
                         [self.bufferMemonry setObject:image forKey:sourceModel.icon];
                         [imageData writeToFile:fullPath atomically:YES];
                     }
                     //回到主线程刷新UI
                     [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                         //cell.imageView.image = image;
                         //只刷新对应的行,提高tableview的性能
                         [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
                     }];
                     
                     [self.operationMemonry removeObjectForKey:sourceModel.icon];
                 }];
                 [self.operationQueue addOperation:download];
                 [self.operationMemonry setObject:download forKey:sourceModel.icon];
             }
          
         }
       
     }
    

    cell.textLabel.text = sourceModel.title;
    cell.detailTextLabel.text = sourceModel.subTitle;
    return cell;
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值