2010-04-27 55 views
1

我正在使用UITableView來顯示一系列計算的結果。當用戶點擊「計算」時,我將最新結果添加到屏幕上。當添加了新的小區時,UITableViewCell對象被添加到陣列(其由tableView:cellForRowAtIndexPath:索引),然後我用下面的代碼來添加這個新行什麼是顯示在屏幕上:添加單元格和使用UITableView滾動時出現圖形故障

[thisView beginUpdates]; 
[thisView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation: UITableViewRowAnimationFade]; 
[thisView endUpdates]; 

這導致顯示新的單元格。但是,我想立即滾動屏幕,以便新的單元格是屏幕上最下面的單元格。我使用下面的代碼:

[thisView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; 

幾乎的偉大工程。但是,第一次添加和滾動單元格時,它僅在消失之前短暫地出現在屏幕上。視圖向下滾動到正確的位置,但單元不在那裏。用手滾動視圖,直到這個看不見的新單元格的位置在屏幕外,然後再返回,導致單元格出現 - 之後它的行爲正常。這隻會在第一次添加單元格時發生;後續的單元不存在這個問題。它也會發生,無論scrollToRowAtIndexPathinsertRowsAtIndexPath動畫設置的組合如何。

編輯: 現在我已經開始在表的第二個到最後位置插入細胞,而不是結束,問題仍然存在 - 第一次插入時,一個單元是「隱形」直到它離開屏幕並再次返回。有什麼可能導致這種情況,我怎麼能強制細胞一旦被添加到表中繪製?

回答

5

您遇到問題是因爲您更新表時未更新支持該表的數據模型。表格實際上並不知道它們有多少行,也沒有顯示哪些單元格。他們依靠數據源和代表來告訴他們這些事情。你的設計期望表本身來追蹤它們。

insertRowsAtIndexPaths:旨在用於移動表中的現有行,而不是添加全新的邏輯行。當你插入一個全新的單元格時,tableview會丟失它實際上有多少行的軌跡。

之前,你顯示一個新行,你應該做的第一件事就是更新由返回值:

– numberOfSectionsInTableView: 
– tableView:numberOfRowsInSection: 

...以反映增加了新的行。這將使桌子瞭解它有多大。

然後,您需要更新cellForRowAtIndexPath:,以便爲添加的行返回正確的單元格。然後你需要重新加載表格。

完成之後,您應該可以將tableview滾動到最後並使單元格正確顯示。

要記住表格的重要之處在於它們是愚蠢的。該表本身不包含數據,不知道它有多少節和行,以及行和節的順序。關於數據,節,行,單元格和單元格內容的所有邏輯都來自數據源和/或代表。當你想改變表格時,你實際上改變了數據源和/或委託,然後表格會自動反映這些改變。

編輯:

在重讀的父母,我看到你把實際的UITableViewCell對象數據陣列和你有每行一個單元。

這不是tableviews是如何工作的,這將不是最規模超過幾十行。

表視圖旨在成爲一種幻想,允許您顯示具有任意高數字或行的LOGICAL表。爲此,它只保留足夠的UITableViewCell對象以覆蓋UI中可視化顯示的區域。默認的單元格高度爲44像素,這意味着一次tableview將永遠不會超過9個單元格對象。

而不是吃內存中保存沒有顯示的單元格,tableview讓委託出列已經滾動屏幕的單元格,用另一個LOGICAL行的數據重新填充它,然後將其顯示在新的位置。這是在cellForRowAtIndexPath:

你真的需要從你的設計開始。您的數據需要與用戶界面對象分開保存。你不希望在任何時候都有更多的細胞活着,而不是絕對必要的,因爲你的記憶使用會膨脹,你的反應時間會降低。你目前的問題是這種不尋常設計的結果。

當你這樣做時,你可以添加結果行,如上所述。

+0

我的表的行被保存在嵌套數組中。外部NSMutableArray包含每個部分的一個內部NSMUtableArray。每節NSMutableArray包含該節的單元格。'numberOfSectionsInTableView:'返回節數組的數量,'tableView:numberOfRowsInSection:'返回相關節數組中的單元數。 'cellForRowAtIndexPath'使用段和行號在我的數組結構中找到相關的行,並返回它。 – 2010-05-02 17:31:11

+0

我不想看到幾行,更不用說幾十行了。我會研究重新設計,但我也希望有一個短期解決方案。 – 2010-05-02 23:07:41

+0

短期內,您必須確保數據源在返回段和行數時反映結果單元格的添加。在將單元添加到數據數組後,我會調用' - [UITableView reload]'。這應該會導致tableview更新自己的適當數量的部分和行,這將讓它正確顯示自己。然而,你總是會遇到這種設計方面的麻煩,並且總是會帶來很多額外的工作。 – TechZen 2010-05-03 15:01:11

1

嘗試在通過NSTimer或performSelector:withDelay:進行單元更新後進行一些時間偏移的滾動操作。它可以幫助解決所有我認爲需要做更多工作的問題。

+0

這有助於以前,但現在我插入行中間的表,並沒有什麼差異。有什麼建議麼? – 2010-05-02 23:57:41

0

我用什麼Skie建議避免以下列方式問題:加入該行後

立刻道:

[self performSelector:@selector(scrollToDesiredArea:) withObject:newIndexPath afterDelay:0.4f]; 

這叫做如下:

-(void)scrollToDesiredArea:(NSIndexPath *)indexPath{ 
    UITableView *thisView = (UITableView*)self.view; 
    [thisView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; 
} 

的延遲0.4s似乎足以避免故障;更少,它仍然會發生。不過,對於不同型號的iPhone硬件,它可能必須有所不同 - 我只在仿真器上進行測試。

+0

當我剛剛添加一個單元格到最後時,這工作得很好。但是,現在我將一個單元格插入其他單元格的中間,直到它被滾動到屏幕外並且返回時才繪製它。它下面的單元格向下滑動,留下一個空白空間,通過它我可以看到分組的表格背景。一旦這個空間滾動到屏幕外並且返回,它就會顯示爲我添加的單元格,並且從此完美工作。 – 2010-05-02 17:38:13

1

故障可能是由於UITableView認爲自己是所顯示的任何UITableViewCell實例的所有者造成的,並在需要時重用它們。該過程的一部分是在電池上呼叫prepareForReuse。由於您將單元格保存在一個數組中,因此您不希望它們重複使用。嘗試在您的UITableViewCell課程中實施空prepareForReuse。或者按照蘋果的建議,在tableView:cellForRowAtIndexPath:中動態創建單元格。