當創建一個UITableView並且每當你發送一個reloadData消息時,數據源就會爲每個單元發送一個heightForRowAtIndexPath消息。所以如果你的表格有30個單元格,那麼這個消息會被髮送30次。
說這30個單元格中只有6個在屏幕上可見。在這種情況下,當創建併發送reloadData消息時,UITableView將在每個可見行發送一個cellForRowAtIndexPath消息,即該消息被髮送六次。
蘋果爲什麼像這樣實施它?其中一部分原因是,計算行高度比構建和填充整個單元格要便宜得多。鑑於在許多表格中,每個單元格的高度都是相同的,它通常要便宜得多。部分原因是因爲iOS需要知道整個表的大小:這允許它創建滾動條並將其設置在滾動視圖中等。
如果您的行高因尺寸不同而不同可以使用不同數量的文本,您可以使用相關字符串上的sizeWithFont:方法之一來進行計算。這比構建視圖然後測量結果更快。請注意,如果您更改單元格的高度,則需要重新加載整個表格(使用reloadData - 這將詢問代表每個高度,但只詢問可見單元格),或者選擇性地重新加載大小已滿的行改變。
其他材料 如果我理解在評論跟進的問題,以下可能會有幫助:
如果要實現編輯模式,那麼它的情況並不少見需要改變你的表的高度行。例如,您的表格行中可能有文本,並且它們的單元格變得更窄時 - 爲右側的刪除圓圈留出空間 - 您可能希望某些單元格變得更高以容納文本。這裏的基本方法是:
確保tableView:heightForRowAtIndexPath:方法知道您是否處於編輯模式。 (它可以使用isEditing來詢問tableView。)然後讓方法返回正確的高度,這取決於你是否處於編輯模式。
在UITableViewController中的setEditing:animated方法(或者UIViewController,無論你使用什麼 - 取決於你使用什麼,都有一些差異,所以值得仔細檢查文檔)發送reloadData消息到tableView之後你已經改變了它的狀態。這將強制tableView抓住每一行的高度,並將重新獲取可見行的單元格。當您進入編輯模式時,tableView處理使單元變窄,但如果您想在佈局上做更多工作,請在tableView:cellForRowAtIndex:中執行。如上所述,總體策略是找到一種快速計算高度的方法。隨着文字sizeWithFont:(及其變體)可以做到這一點。如果你有圖片等,那麼你可以抓住他們的尺寸並做一些總和。
除了這些步驟之外,您可能還想在切換模式後滾動tableView。如果行的高度不同,那麼切換模式後,表格中的位置將會錯誤。我在這裏採用的一種方法是在重新加載表格以調用執行滾動調整的方法之後,使用performSelector:withObject:afterDelay。您需要使用延遲,以便讓tableView有時間收集新的高度和新的表格單元格。 (這可能是一個更明智的方法。)我根據tableView:cellForRowAtIndexPath:在重載之前和之後屏幕上單元格第一個可見行的origin.y之間的差異做了一些調整以進行滾動調整。所以,例如,爲了在預加載之前得到位置,有點像這樣。
CGPoint offset = [[self tableView] contentOffset];
NSIndexPath* indexPath = [[self tableView] indexPathForRowAtPoint:CGPointMake(0,offset.y)];
CGFloat preCellOffset = [[[self tableView] cellForRowAtIndexPath:indexPath] origin].y;
我已經在我的自定義的UITableViewCell子引入一個類的方法做到了這一點,正如你所提到的。它有效,但我也質疑效率。 – chris 2011-03-14 06:15:09