iOS UITableView 滑動時順序混亂或多個cell內容相同
在使用UITableView時,由於cell的重用機制,在獲取後臺數據並填充cell時,會發生cell重復出現,界面紊亂。但這僅僅在擁有多個section的情況下會出現,沒有滾動的時候,單個section的row顯示的都是正確的。
以下是示例代碼:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath //這個方法是UITableView 的 DataSource方法,作用是用來加載/重用cell的。 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {static NSString *SimpleTableIdentifier = @"SimpleTableIdentifier"; // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: SimpleTableIdentifier]; UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; if (cell == nil) { // ... your code cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: SimpleTableIdentifier]; }return cell; }
這裏面的變量其實每創建一次tableViewController都會出現:
1. SimpleTableIdentifier:cell的標識, dequeueReusableCellWithIdentifier方法會用到。在alloc cell的時候會傳入SimpleTableIdentifier並賦給cell的reuseIdentifier屬性
。如果使用dequeueReusableCellWithIdentifier來獲取cell,就要確保每個indexPath.row所指向的cell的SimpleTableIdentifier唯一。
2. dequeueReusableCellWithIdentifier::這個方法會返回reuseIdentifier與當前SimpleTableIdentifier相同的cell,這也就是造成順序混亂的原因,如果沒有找到,返回nil。
3. cellForRowAtIndexPath::這個方法會返回與當前indexPath相同的cell,所以就算是所有cell的SimpleTableIdentifier都相同,也會得到正確順序,如果沒有找到,返回nil。
總結:
如果在你的程序中,出現排序混亂或cell內容相同的情況,請核對使用的是dequeueReusableCellWithIdentifier方法還是cellForRowAtIndexPath方法。
由於cellForRowAtIndexPath方法不會出現這種情況,所以如果使用的是dequeueReusableCellWithIdentifier方法,請確保每個cell的reuseIdentifier唯一。
但是cell重用的機制也不能忽略,UITableViewCell有一個隊列用來專門存放那些生成過的,但是後來由於滾動tableView而隱藏起來的cell,
比如一個table有20個cell,但是屏幕只能顯示5個,(當然iPhone5可能會顯示6個),那麽就會有其他的cell沒有顯示出來,但是在滑動tableview的時候便會顯現。
而代碼中:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: SimpleTableIdentifier];
就是從隊列中根據標示符取出一個暫時不用的cell,只有cell為nil,也就是隊列中沒有舊的cell的時候,才會執行:
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier: SimpleTableIdentifier];
以此生成一個新的cell。
如果有舊的,就不用執行這個語句了,這樣節省資源,算作一種重用。
在tableView初始化的時候隊列中肯定沒有cell的,所以每個cell生成的時候都會執行一遍這個代碼:
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier: SimpleTableIdentifier];
當屏幕顯示滿了,向上滾動顯示下一行時,就會把第一行隱藏,放到那個隊列中,然後新增加的一行執行語句:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: SimpleTableIdentifier];這時候結果就不是nil了,然後,就跳過語句2了,這樣就節約資源了。
iOS UITableView 滑動時順序混亂或多個cell內容相同