iOS:原生方法实现tableView加载多个图片的cell

实现

#import "MZTableViewController.h"

/// 模型类
@interface MZInfoModel : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *subName;
@property (nonatomic, copy) NSString *imageUrl;

+ (instancetype)modelWithDictionary:(NSDictionary *)dict;

@end

@implementation MZInfoModel

+ (instancetype)modelWithDictionary:(NSDictionary *)dict {
    
    MZInfoModel *model = [[MZInfoModel alloc] init];
    [model setValuesForKeysWithDictionary:dict];
    return model;
}

// 为了防止字典里有的 key,但模型里没有对应的属性而导致 crash
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {}

@end

@interface MZTableViewController ()

@property (nonatomic, strong) NSArray *dataList; ///< 用于存放数据源
@property (nonatomic, strong) NSMutableDictionary *memoryDict; ///< 图片的内存缓存
@property (nonatomic, strong) NSOperationQueue *queue; ///< 下载图片的队列
@property (nonatomic, strong) NSMutableDictionary *operationDict; ///< 操作缓存

@end

@implementation MZTableViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
}


#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.dataList.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *ID = @"ReuseId";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID forIndexPath:indexPath];
    
    MZInfoModel *model = self.dataList[indexPath.row];
    cell.textLabel.text = model.name;
    cell.detailTextLabel.text = model.subName;
    
    // 读取内存中的图片
    UIImage *image = [self.memoryDict objectForKey:model.imageUrl];
    
    if (image) {// 内存中有图片
        cell.imageView.image = image;
        NSLog(@"使用了内存中的图片");
        
    } else {// 内存中不存在对应的图片
        // 先去缓存中读取
        NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
        NSString *fileName = [model.imageUrl lastPathComponent];
        NSString *fullPath = [cachePath stringByAppendingPathComponent:fileName];
        
        // 检查磁盘缓存
        NSData *data = [NSData dataWithContentsOfFile:fullPath];
        
        if (data) {// 如果磁盘中存在图片
            UIImage *image = [UIImage imageWithData:data];
            cell.imageView.image = image;
            [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
            
            NSLog(@"读取了磁盘中的图片");
            // 写入内存缓存
            [self.memoryDict setValue:image forKey:model.imageUrl];
        } else {// 磁盘中不存在,就去下载
            
            // 处理下载图片耗时时间长的场景:检查图片是否在下载,如果没有,就去下载
            NSBlockOperation *operation = [self.operationDict objectForKey:model.imageUrl];
            
            if (!operation) {
                // 防止图片没有下载出来时,导致图片显示错乱的问题
                cell.imageView.image = nil;
                
                operation = [NSBlockOperation blockOperationWithBlock:^{
                    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:model.imageUrl]];
                    
                    // 将图片的二进制流写入磁盘
                    [data writeToFile:fullPath atomically:YES];
                    
                    UIImage *image = [UIImage imageWithData:data];
                    
                    // 如果图片不存在
                    if (!image) {
                        // 移除图片的下载操作
                        [self.operationDict removeObjectForKey:model.imageUrl];
                        return;
                    }
                    // 将图片缓存到内存
                    [self.memoryDict setValue:image forKey:model.imageUrl];
                    
                    // 图片下载成功后,移除图片的下载操作
                    [self.operationDict removeObjectForKey:model.imageUrl];
                    
                    // 切换到主线程刷新UI
                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                        cell.imageView.image = image;
                        [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
                        
                        NSLog(@"下载图片");
                    }];
                }];
                // 添加操作到缓存
                [self.operationDict setValue:operation forKey:model.imageUrl];
                [self.queue addOperation:operation];
            }
        }
    }
    
    return cell;
}


#pragma mark - Getter

- (NSOperationQueue *)queue {
    if (!_queue) {
        _queue = [[NSOperationQueue alloc] init];
        // 设置最大并发数
        _queue.maxConcurrentOperationCount = 5;
    }
    return _queue;
}

- (NSMutableDictionary *)operationDict {
    if (!_operationDict) {
        _operationDict = [NSMutableDictionary dictionary];
    }
    return _operationDict;
}

- (NSArray *)dataList {
    if (!_dataList) {
        // 获取文件数据源
         NSArray *source = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"SourceData.plist" ofType:nil]];
        
        NSMutableArray *array = [NSMutableArray array];
        [source enumerateObjectsUsingBlock:^(NSDictionary *obj, NSUInteger idx, BOOL * _Nonnull stop) {
            [array addObject:[MZInfoModel modelWithDictionary:source[idx]]];
        }];
        _dataList = array;
    }
    return _dataList;
}

@end

SourceData.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <dict>
        <key>name</key>
        <string>人民重重0</string>
        <key>subName</key>
        <string>爱编程0</string>
        <key>imageUrl</key>
        <string>https://img.tuzhaozhao.com/2019/03/13/b2ec25f9bd4d2f01_300x300.jpg</string>
    </dict>
    <dict>
        <key>name</key>
        <string>人民重重1</string>
        <key>subName</key>
        <string>爱编程1</string>
        <key>imageUrl</key>
        <string>https://img.tuzhaozhao.com/2019/03/13/38a15ebde8697ecb_300x300.jpg</string>
    </dict>
    <dict>
        <key>name</key>
        <string>人民重重2</string>
        <key>subName</key>
        <string>爱编程2</string>
        <key>imageUrl</key>
        <string>https://img.tuzhaozhao.com/2019/03/04/b8b13c27b20c2692_300x300.jpg</string>
    </dict>
    <dict>
        <key>name</key>
        <string>人民重重3</string>
        <key>subName</key>
        <string>爱编程3</string>
        <key>imageUrl</key>
        <string>https://img.tuzhaozhao.com/2019/02/12/80cfd95fc8b42a90_300x300.jpg</string>
    </dict>
    <dict>
        <key>name</key>
        <string>人民重重4</string>
        <key>subName</key>
        <string>爱编程4</string>
        <key>imageUrl</key>
        <string>https://img.tuzhaozhao.com/2019/02/12/642e00168836ca5e_300x300.jpg</string>
    </dict>
    <dict>
        <key>name</key>
        <string>人民重重5</string>
        <key>subName</key>
        <string>爱编程5</string>
        <key>imageUrl</key>
        <string>https://img.tuzhaozhao.com/2019/01/23/1e8ec7195a25fb36_300x300.jpg</string>
    </dict>
    <dict>
        <key>name</key>
        <string>人民重重6</string>
        <key>subName</key>
        <string>爱编程6</string>
        <key>imageUrl</key>
        <string>https://img.tuzhaozhao.com/2019/01/23/ed8933509da89255_300x300.jpg</string>
    </dict>
    <dict>
        <key>name</key>
        <string>人民重重7</string>
        <key>subName</key>
        <string>爱编程7</string>
        <key>imageUrl</key>
        <string>https://img.tuzhaozhao.com/2019/01/12/6523d1ad55f60928_300x300.jpg</string>
    </dict>
    <dict>
        <key>name</key>
        <string>人民重重8</string>
        <key>subName</key>
        <string>爱编程8</string>
        <key>imageUrl</key>
        <string>https://img.tuzhaozhao.com/2019/01/08/d4e754b68ddb29f3_300x300.jpg</string>
    </dict>
    <dict>
        <key>name</key>
        <string>人民重重9</string>
        <key>subName</key>
        <string>爱编程9</string>
        <key>imageUrl</key>
        <string>https://img.tuzhaozhao.com/2019/01/08/cef0f09f48f9e1bd_300x300.jpg</string>
    </dict>
    <dict>
        <key>name</key>
        <string>人民重重10</string>
        <key>subName</key>
        <string>爱编程10</string>
        <key>imageUrl</key>
        <string>https://img.tuzhaozhao.com/2019/01/02/061f708898d04be1_300x300.jpg</string>
    </dict>
    <dict>
        <key>name</key>
        <string>人民重重11</string>
        <key>subName</key>
        <string>爱编程11</string>
        <key>imageUrl</key>
        <string>https://img.tuzhaozhao.com/2018/12/29/19fa17bb12716b95_300x300.jpg</string>
    </dict>
    <dict>
        <key>name</key>
        <string>人民重重12</string>
        <key>subName</key>
        <string>爱编程12</string>
        <key>imageUrl</key>
        <string>https://img.tuzhaozhao.com/2018/12/07/caa6c6d36f87584b_300x300.jpg</string>
    </dict>
    <dict>
        <key>name</key>
        <string>人民重重13</string>
        <key>subName</key>
        <string>爱编程13</string>
        <key>imageUrl</key>
        <string>https://img.tuzhaozhao.com/2018/11/09/28120072111a8b22_300x300.jpg</string>
    </dict>
    <dict>
        <key>name</key>
        <string>人民重重14</string>
        <key>subName</key>
        <string>爱编程14</string>
        <key>imageUrl</key>
        <string>https://img.tuzhaozhao.com/2018/10/31/d568ab1fa75c628d_300x300.jpg</string>
    </dict>
</array>
</plist>
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容