利用RunLoop最佳化tableView

來源:互聯網
上載者:User

程式碼範例

代碼可以到這裡下載,傳送門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;}


第二步,初始化可變數組用來儲存任務(代碼塊)

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;


第三步,建立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];        });    });}


第四步,將任務添加到數組儲存

//新增工作進數組儲存-(void)addTasks:(SaveFuncBlock)taskBlock{    [self.saveTaskMarr addObject:taskBlock];    //超過每次最多執行的任務數就移出當前數組    if (self.saveTaskMarr.count > self.maxTasksNumber) {        [self.saveTaskMarr removeObjectAtIndex:0];    }}


第五步,在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;}


第六步,監聽RunLoop 第七步,也是最關鍵的步驟,使用定時器,保持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:,同樣的道理也可以應用於其他情境。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.