2012-10-17 202 views
0

我有一個問題,從表視圖中刪除一行。這是在按下行上的按鈕時調用的代碼。我使用了tag參數來告訴我正在處理哪一行,這就是爲什麼我在最後調用reloadTableView來重新應用所有標記的原因。如果我更新可見的行,我有崩潰。所以我一定在這裏做錯了什麼?從UITableView刪除行導致崩潰

- (void) deleteLineItem:(id)sender 
{ 
    UIButton *deleteBtn = sender; // Need to get tag (which was set to table row) 
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:(deleteBtn.tag/3) inSection:0]; 
    NSLog(@"Removed entry at %d, with tag %d", indexPath.row, deleteBtn.tag); 
    [self.productItems removeObjectAtIndex:indexPath.row]; 

    [self.tableview beginUpdates]; 
    [self.tableview deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight]; 
    [self.tableview endUpdates]; 

    // Hack to keep table animation ok as we have to do it after the row delete above 
    [self performSelector:@selector(reloadTableview) withObject:nil afterDelay:0.35]; 
} 

在這種情況下,我有兩行在表中。 數據源如下:

Printing description of self->productItems: 
(__NSArrayM *) productItems = 0x084fa3b0 @"2 objects" 

的indexPath如下:

Printing description of indexPath: 
<NSIndexPath 0x1069bff0> 2 indexes [0, 1] 

當endUpdates梅託德叫我碰到下面的崩潰在控制檯

2012-10-17 17:04:33.424 myAppname[5782:15203] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]' 
*** First throw call stack: 
(0x1bf0022 0x1918cd6 0x1bdcd88 0xa5553 0xa576b 0x925420 0x963284 0x9633d0 0x925219 0x8fd4f2 0x8fa4c3 0x9050b7 0x9050e5 0xa6ae1 0x1bf1e99 0x87814e 0x8780e6 0x91eade 0x91efa7 0x91e266 0xb39a1a 0x1bc499e 0x1b5b640 0x1b274c6 0x1b26d84 0x1b26c9b 0x25007d8 0x250088a 0x875626 0x1f2ba 0x2ba5) 
terminate called throwing an exception(lldb) 

我有不知道爲什麼會造成問題。

+0

其實我真的不喜歡你的哈克...:) – Peres

+0

我也沒有,但我不能讓動畫正確地工作沒有它 – d0n13

+0

你也可以發佈代碼的一部分,這個'deleteLineItem:'被調用? –

回答

1

該代碼看起來不太健壯。似乎你已經將deleteBtn.tag設置爲一個錯誤的值(在3到5之間,更精確),你只有一個單元。只是一個猜測。

對於這樣的任務,我使用的更強大的技術是在我的UITableViewCell子類中實現IBAction,然後通過委託將單元本身作爲參數傳播給控制器。在控制器然後我檢索索引通過

[self.tableView indexPathForCell:cell]; 

這樣我就避免了這樣的黑客。

+0

見下文,我將格式化好一點 – d0n13

0

@ilimiacs是的,這是正確的,這將是一個很好的方法來做到這一點。但單元格很複雜,有兩個按鈕和兩個文本字段。

該標籤用於通過除以3得到該行(每個單元使用3個標籤,0,1,2)來確定我在哪個單元上。然後,標籤3將是第1行,這就是爲什麼我除以3的原因。

但是我確實有單元類,我會考慮使用委託來完成它的可行性,它很容易使用按鈕,但並不那麼容易對於文本字段,因爲它是一種形式,並且我們有下一個/上一個按鈕,它們將您從一個字段引導到另一個字段,這些標籤使這一切變得簡單。

無論如何,我會接受這個答案,因爲它肯定有幫助,也許我可以把它變成完整的解決方案。

+0

1.我沒有看到爲什麼這不應該與代表團一起工作的原因。 2.我清楚地看到你的代碼是如何更容易編寫的。然而,魯棒性的論點仍然存在:在你的代碼中,你會假設什麼時候系統被允許訪問你的單元格,什麼時候沒有。例如,您的崩潰可能是由併發問題導致的。當離開更新塊時,單元格可能仍然存在於tableView中,而您的數據源已經更新。所以無論你是否乾淨還取決於'reloadTableview'的實現。你可以避免這種情況。 – ilmiacs

0

@ilmiacs謝謝你的建議。我按照你的說法實施,擺脫了標籤,現在所有東西都在表現自己。重新實現有點痛苦,但它導致了更少的黑客和更可讀的代碼。

我能夠更新第一行而不是重新計算其餘行的所有標記值。我需要從第一個刪除按鈕,如果它是你看到的最後一行...現在你可以看到它更簡單一些。

- (void) deleteCell:(NSIndexPath *)indexPath 
{ 
    NSIndexPath *firstRow = [NSIndexPath indexPathForRow:0 inSection:0]; 
    [self.productItems removeObjectAtIndex:indexPath.row]; 

    [self.tableview beginUpdates]; 
    [self.tableview deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight]; 
    [self.tableview reloadRowsAtIndexPaths:[NSArray arrayWithObject:firstRow] withRowAnimation:UITableViewRowAnimationNone]; 
    [self.tableview endUpdates]; 
} 

謝謝...