web-dev-qa-db-ja.com

StoryBoardで設計されたUITableViewから静的セルを削除する方法

解決策はおそらく非常に単純ですが、私はそれを見つけることができませんでした..!

ストーリーボード(iOS 5)を使用して、tableViewControllerと、各セクション内に異なる静的セルを持つ5つのセクションを持つ設計された静的テーブルビューを用意しました。

私の質問は、viewWillAppearのセルをプログラムで削除する方法ですか?

たとえば、日付用に設計されたセルがあります

IBOutlet UITableViewCell * cellForDate;

そして、日付がない場合は、自分のセルを削除します。

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

私はもう試した [tableView deleteRowsAtIndexPaths...]機能しませんでした

誰かがアイデアを得ましたか?

28
Marc

セルが表示される前に、UITableViewDelegateの-​​ tableView:willDisplayCell:forRowAtIndexPath: メソッド。これが、セルの外観を操作できる最後の方法です。ただし、これによってセルが必要とするスペースが削除されることはないため、- tableView:heightForRowAtIndexPath: 同じプロトコルのメソッド。

最も堅牢な別の方法は、セクション内の日付セルが必要かどうかを判断し、結果に応じて、セクション内の適切な行数を返し、状況に応じて他のセクション行セルを返す方法を考案することですアカウント。次に、viewWillAppearでtableViewのデータをリロードします。

35
macbirdie

うまくいけば、これはもう少し普遍的な解決策ですが、それでも完璧ではありません

- (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にすると、リストから効果的に削除されます。セルを非表示にしない場合は、スーパーから高さを取得するため、通常は何が起きても起こります。

これに関する唯一の問題は、開始セルと終了セルがリストまたはグループの上部と下部の仕切りを担当していることです。したがって、グループの最後のセルを非表示にすると、グループの下部の仕切りは、全幅ではなく通常の行のようにわずかに挿入されます。これは、一番上の行または一番下の行を非表示にしていて、仕切りを使用していて、完全に標準的な表示に関心がある場合にのみ問題になります。私の場合の最善の解決策は、単に上部または下部の行を非表示にしないことでした。非表示になっている可能性のあるコンテンツをグループの中央に移動しました。代わりに、それが標準ではないことを受け入れるか、テーブルの行分割線を無効にすることもできます。

26
ima747

Swift

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)
    }
}
12
Henry

テーブルビューセルを完全に削除する場合は、行に対応するindexPathを指定してdeleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]を呼び出すだけです。また、numberOfRowsInSection:によって返される行数を減らす必要があります。

ただし、特定の行が存在する場合と存在しない場合があるため、静的テーブルビューから不要な静的テーブルビューセルを一時的に「削除」する方法を探していました。また、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;
}

Tableviewコントローラーの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];
}

テーブルビューのデータソースデリゲート:

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

そして最後に

- (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]で利用できるということです。静的テーブルビューセルの永続的なストレージにはそれを使用してください。次に、必要に応じて行数を調整し、テーブルビューデリゲートのcellForRowAtIndexPath:で行を正しくマップします(つまり、表示するセルに対応する格納されたセルの行を取得します)。

updateSettingsDisplayメソッドは、それを保持するクラスからtableviewコントローラーで呼び出すことができます。呼び出されたときにtableviewコントローラーが表示されていない場合は、状態を更新し、次に表示されるようになるまで待機して表示を変更します。

3
BeccaP
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
    }
}
1
Yaman

あなたはこれを見たいかもしれません

https://github.com/xelvenone/StaticDataTableViewController/

使用法

self.hideSectionsWithHiddenRows = YES; //YES, NO
[self cell:self.outletToMyStaticCell1 setHidden:hide];
[self cell:self.outletToMyStaticCell2 setHidden:hide];
[self reloadDataAnimated:YES];
0
Peter Lapisu

参考までに(できればコメントします)、ストーリーボードからグループ化された静的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);
    }
0
Coruscate5