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代表了不同的隊列,重用時按隊列順序先進先出,一輪之後再重新從第一個開始重用。