服務端擷取到通訊錄更新到本地,打算使用隊列逐條處理,查找了下隊列如何使用,先實作個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實作多線程
本文之後會不定期更新開發中遇到的問題及解決方式