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

2019-09-26  本文已影响0人  春暖花已开

实现

#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>
上一篇 下一篇

猜你喜欢

热点阅读