2014-02-11 28 views
0

我有什麼可能看起來像一個非常奇怪的問題(它確實給我!)UITableViewCell在仍然在屏幕上時被重用?

我使用的是UITableView顯示均含有一UIWebView細胞。我意識到這是一個壞主意,但我不能以其他方式真正做到這一點。

我緩存每個單元的高度時UIWebView完成加載,然後調用:

[self.tableView beginUpdates]; 
[self.tableView reloadRowsAtIndexPaths:@[cellIndexPath] 
         withRowAnimation:UITableViewRowAnimationNone]; 
[self.tableView endUpdates]; 

所有鍺代碼是in a Gist here

我還將UIWebView s緩存在數據源的字典中,因此可以在單元重新加載時重用它。

這似乎是一種工作,但我遇到了很多問題,由此單元格的內容將隨機消失。我已經添加了一些日誌記錄來確定發生了什麼,並且按照什麼順序,並且好像有些單元格正在被重用,同時它們仍然在屏幕上

我在日誌中看到這一點的同時向下滾動:在這種情況下

2014-02-11 13:45:49.091 EApp[45936:70b] Generating cell for 1: Panning 
2014-02-11 13:45:49.245 EApp[45936:70b] Generating cell for 2: Calibration 
2014-02-11 13:45:50.063 EApp[45936:70b] Generating cell for 3: Aperture Priority 
2014-02-11 13:45:50.063 EApp[45936:70b] Reusing cell: Stopping down 

「停止下降」是仍在屏幕上的一個細胞。 「生成單元格」項記錄在數據源的cellForRowAtIndexPath內部以及單元格「prepareForReuse」內的「重用」消息內。

有誰知道這裏會發生什麼?我知道這看起來很複雜。

+2

「我遇到了很多的問題,從而使細胞的內容會隨機消失。」那是真正的問題。大多數時候,罪魁禍首都在你的'table:cellForRowAtIndexPath:'中 - 看到它的代碼將極大地簡化找出錯誤。 – dasblinkenlight

+0

你爲什麼要重新加載一些單元格? (爲了什麼目的?) – AncAinu

+0

這聽起來像是你添加一個子視圖(可能是你的UIWebView)到一個不同的單元格,它將它從它開始的單元格中移除。 – Holly

回答

1

下面一行在你prepareForReuse可能是罪魁禍首:

if ([self.contentWebView isDescendantOfView:self.contentWebView]) { 
    [self.contentWebView removeFromSuperview]; 
} 

由於contentWebView從不自身的後代,也不會從細胞去除,cellForRowAtIndexPath後的內容查看將包含網頁視圖:

你大概的意思是說:

if ([self.contentWebView isDescendantOfView:self.contentView]) { 
    [self.contentWebView removeFromSuperview]; 
} 

或者乾脆:

[self.contentWebView removeFromSuperview]; 
+0

你先生,是聖人。 – obeattie

0

UITableView的一個特性/侷限性是,您不知道是否創建或重用了單元,是否可以不依賴單元。你應該始終能夠處理這兩個問題。

GENERALLY,當您撥打-reloadRowsAtIndexPaths:withRowAnimation:時,您將從該indexPath中獲取單元格以重用。如果這個indexPath在屏幕上,它將是一個在屏幕上的單元格。

+0

我遇到的問題更多的是與滾動有關:仍然在屏幕上的單元格在滾動時被重複使用以創建新單元格。 – obeattie

0

我不知道這是否是問題,但在你提供的代碼,你甚至不初始化你的...

我甚至驚訝它的工作原理。

static NSString *CellIdentifier = @"FeedItemCell"; 
EFeedItemCell *cell = [self.tableViewController.tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

您應該添加到它:

if (!cell) { 
    cell = [EfeedItemCell alloc] initWithReus....]; 
} 
+0

我已經添加了(並更新了Gist),但它似乎沒有做任何事情。我也在if語句中的代碼中添加了一個斷點,看起來它從來沒有被調用過。雖然謝謝! 如果它有所不同,單元格將放置在'.storyboard'文件中(除了'UIWebView')。 – obeattie

+0

所以你的桌子從別的地方餵食...... dequeueReusableCell從桌子上收集現有的細胞。現有的細胞來自某個地方。 我的意思是,如果你從不寫[[EFeedItemCell alloc] init],那麼你的單元就像耶穌,從無處生下。對於耶穌我不知道,但對於你的牢房來說不可能。 但最終,如果你甚至不知道你的細胞在哪裏創建,那麼確定你可能會遇到問題。 – AncAinu

0

從你的代碼看起來你是緩存網頁視圖,然後是他們編程方式添加到細胞。這可能會產生類似於我在通過時遇到的隨機問題。

您必須在故事板中使用EFeedItemCellWebView。只需添加一個UIWebView並將類名更改爲您的自定義類。然後,當數據被加載只是簡單地改變其內容- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

+0

確保創建IBOutlet連接到自定義UIWebview。 –

+0

你的建議我: 1.添加'EFeedItemCellWebView'我'.storyboard'文件 2.創建*另一個*'EFeedItemCellWebView'表視圖數據源 3.交換一個用於其他在裏面的數據源,一旦(數據源創建的)完成加載? 對不起,困惑! – obeattie

+0

不!不要創建另一個'EFeedItemCellWebView'。重新加載時,只需更改單元格中'EFeedItemCellWebView'的內容即可。當我在數組中保存視圖並在UITableViewCells中使用它們時,我遇到了類似的問題。你也不需要緩存高度。在運行時計算它們,除非它們讓應用程序太慢。 –

相關問題