RunLoopによるtableViewの最適化

5619 ワード

コードの例
コードはここでダウンロードすることができて、ドアdemoを転送します
テキストリンク:http://www.qingpingshan.com/rjbc/ios/214222.html     iOSの開発において、UItableViewの最適化は従来からよく言われている問題であり、よく使われているプリロード、キャッシュなどの方法のほか、RunLoopのサイクルを利用しても超清大図のスムーズなロードを実現することができ、具体的な使用方法は一つのdemoを利用して詳細に理解する
まず、ネットワークからUItableViewCellにハイビジョンマップをロードし、各Cellに複数の画像をロードする必要があります.cellの数が多すぎる場合、スムーズさとロード速度を維持する必要があります.
簡単な分析を行います
1,       Runloop  ,         runloop

2,              ,

               。*
3,  runloop
         runloop

では、コード実装を検討することができます.
まずuitableviewの基本効果を実現します
@property (strong,nonatomic) UITableView* showImageTableView;
//   
-(UITableView *)showImageTableView{

    if (!_showImageTableView) {
        _showImageTableView = [[UITableView alloc]initWithFrame:[UIScreen mainScreen].bounds style:UITableViewStylePlain];
        _showImageTableView.backgroundColor = [UIColor yellowColor];
        _showImageTableView.delegate = self;
        _showImageTableView.dataSource = self;
    }

    return _showImageTableView;
}
//  
    [self.showImageTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ShowImageTableViewReusableIdentifier];
//  
    [self.view addSubview:self.showImageTableView];
//     
#pragma mark- UITableViewDelegate
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:ShowImageTableViewReusableIdentifier];
    //  cell   3   
    for (int i = 0; i < 3; i++)
    {
       #          
    }

    return cell;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return 399;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

    return 135;
}

ステップ2では、タスク(コードブロック)を格納するために可変配列を初期化します.
typedef void(^SaveFuncBlock)();

//       
@property (nonatomic, strong) NSMutableArray *saveTaskMarr;

//     (               )
@property (nonatomic, assign) NSInteger maxTasksNumber;

//        
@property (nonatomic, copy) SaveFuncBlock saveFuncBlock;


-(NSMutableArray *)saveTaskMarr{

    if (!_saveTaskMarr) {

        _saveTaskMarr = [NSMutableArray array];
    }

    return _saveTaskMarr;
}

    self.maxTasksNumber = 18;

第3歩、新しいcellで画像を追加する方法
-(void)addImageToCell:(UITableViewCell*)cell andTag:(NSInteger)tag{

    UIImageView* cellImageView = [[UIImageView alloc]initWithFrame:CGRectMake(tag*(ImageWidth+5), 5, ImageWidth, ImageHeight)];

    dispatch_async(dispatch_get_global_queue(0,0), ^{

        NSData* imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://img5.duitang.com/uploads/item/201312/14/20131214173346_iVKdT.jpeg"]];

        dispatch_async(dispatch_get_main_queue(), ^{

            cellImageView.image = [UIImage imageWithData:imageData];
            [cell.contentView addSubview:cellImageView];
        });
    });
}

ステップ4では、配列保存にタスクを追加します.
//         
-(void)addTasks:(SaveFuncBlock)taskBlock{

    [self.saveTaskMarr addObject:taskBlock];
    //                   
    if (self.saveTaskMarr.count > self.maxTasksNumber) {

        [self.saveTaskMarr removeObjectAtIndex:0];
    }

}

ステップ5 cellForRowメソッドで、メソッドを追加します.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:ShowImageTableViewReusableIdentifier];

    for (int i = 0; i < 3; i++)
    {
        //       
        __weak typeof(self) weakSelf = self;
        [self addTasks:^{
            //       
            [weakSelf addImageToCell:cell andTag:i];
        }];
    }

    return cell;
}

ステップ6 RunLoopの傍受
7ステップ目は、タイマーを使ってRunLoopサイクルを維持する最も重要なステップでもあります.
//   ,  runloop       
@property (nonatomic, weak) NSTimer *timer;

self.timer = [NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(setRunLoop) userInfo:nil repeats:YES];

//               runloop     ,       
-(void)setRunLoop{}

最後のステップはrunLoopループでイベントを処理する
//MARK:     
//            RunLoop   
static void Callback(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info){
    ViewController * vcSelf = (__bridge ViewController *)(info);

    if (vcSelf.saveTaskMarr.count > 0) {

        //              
        SaveFuncBlock funcBlock = vcSelf.saveTaskMarr.firstObject;
        funcBlock();
        [vcSelf.saveTaskMarr removeObjectAtIndex:0];
    }
}

よし.ここまで、私たちが望んでいる効果は基本的に出てきました.皆さんは試してみてください.hushed:、同じ理屈で他のシーンにも適用できます.