服务端获取到通讯录更新到本地,打算使用队列逐条处理,查找了下队列如何使用,先实现个demo,如下:
#import "ViewController.h"
@interface ViewController ()<UITableViewDelegate, UITableViewDataSource>
// operation 列表
@property (nonatomic, strong) NSMutableDictionary *operations;
// 队列
@property (nonatomic, strong) NSOperationQueue *queue;
// 表示图
@property (nonatomic, strong) UITableView *tableView;
// 数据
@property (nonatomic, strong) NSMutableArray *datasource;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 添加数据
for (int i = 0; i < 100; i ++) {
NSDictionary *dic = @{@"key":[NSString stringWithFormat:@"operation %d", i]};
[self.datasource addObject:dic.mutableCopy];
}
// 刷新表
[self.tableView reloadData];
}
#pragma mark - Table view datasource and delegate
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.datasource.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = @"identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
}
NSMutableDictionary *dic = self.datasource[indexPath.row];
NSString *key = dic[@"key"];
cell.textLabel.text = key;
NSString *subKey = dic[@"subkey"];
if (subKey.length > 0) {
cell.detailTextLabel.text = subKey;
} else {
// 展示默认数据,通过队列逐条更新数据
cell.detailTextLabel.text = @"waiting";
NSOperation *operation = self.operations[key];
if (!operation) {
// 操作列表中不存在则新建
operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@", key);
sleep(1);
// 更新数据
dic[@"subkey"] = key;
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// 回到主线程更新UI
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}];
// 操作完成,从操作列表删除
[self.operations removeObjectForKey:key];
}];
// 将操作对象加入队列
[self.queue addOperation:operation];
// 加入操作列表
self.operations[key] = operation;
}
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 55;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (NSMutableDictionary *)operations
{
if (!_operations) {
_operations = [NSMutableDictionary dictionary];
}
return _operations;
}
- (NSOperationQueue *)queue
{
if (!_queue) {
_queue = [[NSOperationQueue alloc] init];
_queue.maxConcurrentOperationCount = 1;
}
return _queue;
}
- (UITableView *)tableView
{
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
[self.view addSubview:_tableView];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.tableFooterView = [[UIView alloc] init];
}
return _tableView;
}
-(NSMutableArray *)datasource
{
if (!_datasource) {
_datasource = [NSMutableArray array];
}
return _datasource;
}
@end
网上已经有很多详细的讲解文章,这里不再赘述,贴几个传送门
iOS操作队列
iOS 开发 多线程详解之NSOperation实现多线程
本文之后会不定期更新开发中遇到的问题及解决方式