2011-11-24 83 views
23

該解決方案可能非常簡單,但我無法找到它。如何從StoryBoard中設計的UITableView中刪除靜態單元

使用故事板(iOS 5),我有一個tableViewController,以及一個帶有5個部分的設計STATIC tableview,每部分內部都有不同的靜態單元格。

我的問題是:如何在viewWillAppear中以編程方式刪除單元格?

例如,我設計了一個日期

IBOutlet UITableViewCell * cellForDate; 

和..一個細胞,如果有沒有日期,我想刪除我的手機。

cellForDate.hidden = true; //Hide the cell, but leave a blank space 

我用盡[tableView deleteRowsAtIndexPaths...]沒有工作

任何人有一個想法?

回答

30

試圖隱藏單元上映之前,在UITableViewDelegatetableView:willDisplayCell:forRowAtIndexPath:方法中。這是您可以操縱單元格外觀的最終方法。但是這不會消除單元格應該佔用的空間,因此您可以嘗試的另一件事是使用同一協議的tableView:heightForRowAtIndexPath:方法將單元行的高度設置爲0。

另一種最健壯的方法是設計一種方法來確定是否需要該部分中的日期單元格,並根據結果返回該部分中的適當行數,並返回其他部分行單元格考慮到這種情況。然後在viewWillAppear上重新加載tableView的數據。

+1

實際上,這是我發現解決問題的唯一方法,使用方法heightForRowAtIndexPath,爲IndexPath開關並在此函數中進行驗證。如果它是零,我用IBOutlet UITableViewCell引用隱藏單元格,並返回0 ..單元格消失!有20多個細胞時會變得有點令人毛骨悚然,但它效果很好! – Marc

+1

這解決了所有問題https://github.com/xelvenone/StaticDataTableViewController/ –

0

你需要把beginUpdates後刪除通話和endUpdates前:

[tableView beginUpdates]; 
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:r inSection:s]]]; 
[tableView endUpdates]; 

在回答您的評論:

- (NSInteger)tableView:(UITableView)tableView numberOfRowsInSection:(NSInteger)section { 
    NSInteger ret; 
    switch (section) { 
     case 0: 
      // sectionZeroRows doesnt have to be a 
      // property (an attribute works just fine), but it 
      // helps with explaining this example. 
      ret = self.sectionZeroRows; 
      break; 
     // ... 
    } 
    return ret; 
} 

- (void)someMethod { 
    --self.sectionZeroRows; 
    [tableView beginUpdates]; 
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]]]; 
    [tableView endUpdates]; 
} 
+0

它給我的崩潰錯誤:** *因未捕獲異常'NSInternalInconsistencyException'而終止應用程序,原因:'無效更新:第4節中的行數無效。更新(3)後現有節中包含的行數必須等於該部分在更新之前(3),加上或減去從該部分插入或刪除的行數(插入0,刪除1),加上或減去移入或移出該部分的行數(移入0,移出0 )「。 – Marc

+0

哦,是的,你需要設置該部分的單元格數量..在你的'tableView:numberOfRowsInSection:'方法中,無論變量是持有行數還是減1,這個方法將返回4而不是5部分(或者很多是必要的)。 – chown

+0

好吧我明白了,我正在嘗試一種新的方式,在iOS 5中使用TableViewController來處理故事板和tableview,並且我沒有覆蓋委託和數據源方法..因爲我的數據源是我的故事板中包含的靜態表..///////如何使用numberOfRowsInSection來知道我是否剛刪除了一行,因爲我正在從viewDidAppear方法中刪除該行。我應該爲每個部分保留一個var,並且只更新我的var? – Marc

-1
// just authed with facebook, and I want to delete the first 3 rows of my 4 row table that are no longer necessary  
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section { 
    if(wantsFacebook) 
     return 1; 

    return 4; 
} 

提交更新後,的tableView將調用numberOfRowsInSection委託獲得的行更新的數目,並且必須是各行之間的正確和/差,當你啓動插入/刪除,行,當你結束插入/刪除

3

如果要永久刪除表格單元格,只需撥打deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]並使用與您的行對應的indexPath。您還需要減少由numberOfRowsInSection:返回的行數。然而,我正在尋找一種方法來暫時從靜態tableview中「刪除」不需要的靜態tableview單元格,因爲我想要一個特定的行有時在那裏,而其他時間則不是。我也希望能夠從tableview控制器外部按需更新。

我的情況很簡單,因爲它是顯示或隱藏的第一行。你可以推廣以適應你自己的需求。我的tableview控制器是我的數據源委託。

首先,我創建的實現代碼如下控制器的公共方法來更新狀態變量並觸發重新顯示:

- (void)updateSettingsDisplay:(BOOL)hideSetting 
{ 
    if (hideSetting == self.hideSetting) { 
     return; // no need to do anything because it didn't change 
    } 

    self.hideSetting = hideSetting; 
    self.numRows = (hideSetting)? kNumRowsWithSetting : kNumRowsWithoutSetting; 

    // redisplay only if we're visible 
    if (!self.viewJustLoaded && (self.navController.visibleViewController == self)) { 
     [self.tableView reloadData]; 
    } 
    self.viewJustLoaded = NO; 
} 

的實現代碼如下控制器的viewDidLoad樣子:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    // check whether or not to display out-of-coverage tableview cell 
    self.hideSetting = YES; // initial value; could just as easily be NO 
    self.viewJustLoaded = YES; 
    [self updateSettingsDisplay]; 
} 

的tableview中的數據 - 來源代表:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    // Return the number of rows in the section. 
    return self.numRows; 
} 

and final LY

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    // set row to the index of the stored tableView cell that corresponds to the 
    // cell you want (its location in the static tableview from your storyboard) 
    NSInteger row = indexPath.row; 
    if (self.hideSetting) { 
     // skip drawing setting's tableviewcell (since the setting we're hiding is 
     // first, we can just increment the row to get the one we want) 
     ++row; 
     assert(row < kTotalRows); // bounds checking just to convince yourself (remove after testing) 
    } 
    // get a new index path since the row field is read-only 
    NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:row inSection:indexPath.section]; 

    // grab the cell from super that corresponds to the cell you want 
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:newIndexPath]; // static table 

    return cell; 
} 

的訣竅是靜態細胞總是可以在[super tableView:tableView cellForRowAtIndexPath:newIndexPath] - 所以使用您的靜態的tableview細胞的永久存儲。然後根據需要進行調整的行數,行正確映射在你的tableview委託的cellForRowAtIndexPath:(即獲得對應於要顯示單元格中的存儲單元格的行)。

updateSettingsDisplay方法可以保留它的任何類你的tableview控制器上進行調用。如果當它被稱爲的tableview控制器是不可見的,它只會更新狀態,並等到明年成爲可見的改變顯示的時間。

+0

答案的第二部分看起來不錯,但第一段使用'deleteRowsAtIndexPaths'沒有效果 –

24

希望這是一個比較通用的解決方案,但它仍然不是很完美

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; 
    if (cell.hidden) { 
     return 0; 
    } else { 
     return [super tableView:tableView heightForRowAtIndexPath:indexPath]; 
    } 
} 

使用此方法,您將您的IBOutlet綁定單元設置爲隱藏,並且那麼當表嘗試顯示一行時,它首先檢查如果單元格(使用超級調用來獲取細胞)應該被隱藏,如果是,則返回0的高度有效地從列表中刪除。如果細胞不應該隱藏,那麼它會從超級獲得高度,所以通常發生的任何事情都會發生。

與此唯一的問題是,開始和結束細胞負責在列表或組的頂部和底部的分隔符。所以,如果你隱藏的最後一個單元的一組在該組的底部分頻器將略有喜歡它是正常的行而不是全幅的插圖。這只是一個問題,如果你隱藏頂部或底部的行,你正在使用分隔線,你關心完全標準的顯示。在我的情況下,最好的解決方案就是不要隱藏頂部或底部的行。我將可能隱藏的任何內容移到了組中。或者,您可以接受它不太標準,或禁用桌面上的分隔線。

+0

正如你所說這不完美,因爲它創建了一個遞歸溢出,但是如果你知道你想要隱藏的行和它們的狀態,你可以跳過'cellForRowAtIndexPath'調用,它可以很好地工作。 –

+0

@Hola Soy Edu Feliz Navidad我沒有看到任何遞歸。測試iOS 9. –

+0

如果您的cellForRowAtIndexPath以某種方式調用heightForRowAtIndexPath,它只會創建一個遞歸。這並非不合理,但也不是標準行爲。如果您遵循佈局的最佳做法,則不應在兩處需要高度。 – ima747

1
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { 

    if(indexPath.section == 1) { //For example 
     return 0 
    } 
} 

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { 
    if(indexPath.section == 1) { 
     cell.hidden = true 
    } 
} 
0

僅供參考,(想如果我可以評論),如果你是從故事板覆蓋分組的靜態UITableView的,那麼你還需要重寫頁眉頁腳& &意見的高度要修改每節/躲了起來。

我還需要將「GetHeight」方法的返回值設置爲零以外的值 - 意味着零值意味着其他值(自動佈局或「未設置」等)。

下面的代碼是在Xamarin的iOS C#,而是直接轉化爲相應的OBJ-C方法:

public override void WillDisplayHeaderView(UITableView tableView, UIView headerView, nint section) 
    { 
     if (section == 0) 
     { 
      headerView = new UIView(new CGRect(0,0,0,0)); 
     } 
    } 

    public override nfloat GetHeightForHeader(UITableView tableView, nint section) 
    { 
     if (section == 0) 
     { 
      return 1f; 
     } 
     return base.GetHeightForHeader(tableView, section); 
    } 

    public override void WillDisplayFooterView(UITableView tableView, UIView footerView, nint section) 
    { 
     if (section == 0) 
     { 
      footerView = new UIView(new CGRect(0, 0, 0, 0)); 
     } 
    } 

    public override nfloat GetHeightForFooter(UITableView tableView, nint section) 
    { 
     if (section == 0) 
     { 
      return 1f; 
     } 
     return base.GetHeightForFooter(tableView, section); 
    } 
1

斯威夫特3

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { 
    if indexPath.section == 0 { 
     cell.isHidden = true 
    } 
} 

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 
    if indexPath.section == 0 { 
     return 0 
    } else { 
     return super.tableView(tableView, heightForRowAt: indexPath) 
    } 
} 
相關問題