iOS親測UITableView重用機制,用事實說話。

UITableView重用機制主要是依靠reuseIdentifier來辨別,以此來建立一個隊列,將建好的Cell放入隊列中,之後直接使用隊列中的Cell,不再新建,極大的提升了TableView的重用性,同時使列表滑動時不會出現卡頓現象。TableView基本上是新手必學,我第一個熟練掌握的控件,及使用得最多的就是TableVIew,重用機制有很多地方很多人都講過,不過我還是要從自己的角度來再次BB下。由於列表內容太長了,不方便直接在界面上截圖,所以只把打印的數據拿出來。

1、重用機制Cell是如何新建的?

很多人以爲Cell在新建的時候只新建一個,其他的都重複使用那一個,但事實上並不是這樣的,新建多少個Cell,並加入重用隊列是取決於初始化時屏幕中能容納多少個Cell,(5S模擬器測試)經測試Cell高44時,新建14個Cell。Cell高120時,count:6,新建6個Cell。


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static int count = 0;
    static NSString *celleIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:celleIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:celleIdentifier];
        cell.selectionStyle = UITableViewCellSelectionStyleGray;
        count ++;
    }
    if (indexPath.row < 10) {
        cell.textLabel.text = [NSString stringWithFormat:@"%ld",(long)indexPath.row];
    
    NSLog(@"count:%d,cellheight:%f",count,cell.frame.size.height);
    return cell;
}


2、Cell重用時是如何取出來的?

在使用120高度的Cell時,重用隊列中將只有6個存儲的Cell,在下方代碼中到第6個Cell,即textLabel == 6時 已用開始使用重用隊列中的Cell,由打印的數據可知,init textLabel爲0,這使用的是第一個存入的隊列Cell,textLabel == 7時, init textLabel爲1,使用的是存入的第二個Cell,一直到使用第六個完成一輪後再重新使用第一個存入的Cell,由此可以推斷,Cell重用時是秉承先進先出的原則,循環使用。


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static int count = 0;
    static NSString *celleIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:celleIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:celleIdentifier];
        cell.selectionStyle = UITableViewCellSelectionStyleGray;
        count ++;
    }
    NSLog(@"init textLabel:%@",cell.textLabel.text);
    if (indexPath.row < 10) {
        cell.textLabel.text = [NSString stringWithFormat:@"%ld",(long)indexPath.row];
    }
    NSLog(@"count:%d,textLabel:%@",count,cell.textLabel.text);
    return cell;
}


3、reuseIdentifier的作用?

在加載第11個Cell的時候開始,Cell的celleIdentifier換成了@"cell2",並且將第11個Cell的textLabel內容換乘@"this is 20",根據截圖可知,由於更換了celleIdentifier,在第11個Cell加載時是沒有init textLabel的,並且count開始自增直至12,說明使用新的celleIdentifier使tableview重新建了一個隊列並且放入了6個新的Cell,並且在6個一輪之後重用了,新隊列裏的Cell。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static int count = 0;
    static NSString *celleIdentifier = @"Cell";
    if (indexPath.row > 10) {
        celleIdentifier = @"Cell2";
    }
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:celleIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:celleIdentifier];
        cell.selectionStyle = UITableViewCellSelectionStyleGray;
        count ++;
    }
    NSLog(@"init textLabel:%@",cell.textLabel.text);
    if (indexPath.row < 10) {
        cell.textLabel.text = [NSString stringWithFormat:@"%ld",(long)indexPath.row];
    }else if (indexPath.row == 11){
        cell.textLabel.text = @"this is 20";
    }
    NSLog(@"count:%d,textLabel:%@",count,cell.textLabel.text);
    return cell;
}



4、爲什麼使用重用機制後我的數據亂掉了?

在解釋第三點時,在第11個Cell之後textLabel一直顯示的是null,這是因爲我沒有在重用後,對這個Cell進行操作,一般在使用重用後,都需要對Cell的數據進行處理。如果沒有處理的話,一種情況就像上面截圖一樣,由於重用隊列裏面的Cell的textLabel就是沒有值的,取出來之後還是不進行操作,即爲null。還有一種情況是打印出this is 20的這種情況,因爲重用隊列裏面的Celld的textLabel裏面有值,取出重用後不進行操作的話就會使用之前隊列裏Cell的textLabel這個值,所以後面有好幾個重用Cell2隊列中第一個存入的Cell時,打印出來的數據也爲this is 20。


總結:不同的reuseIdentifier代表了不同的隊列,重用時按隊列順序先進先出,一輪之後再重新從第一個開始重用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章