天天看點

iOS隊列 NSOperation

服務端擷取到通訊錄更新到本地,打算使用隊列逐條處理,查找了下隊列如何使用,先實作個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實作多線程

本文之後會不定期更新開發中遇到的問題及解決方式