15

UITableViewに標準のNSFetchedResultsControllerが設定されています。ただし、行またはセクションを追加したいと思います(行が望ましいですが、どちらも実際に正常に機能します)。

NSFetchedResultsControllerからのデータを処理するセクションを処理するときに、すべてのNSIndexPathを手動で書き直して、インデックス0のセクションを表示し、インデックス0の行から開始するように仕向けることが、現時点で確認できる唯一の方法です。すぐに混乱してしまう本当に悪い考えのように思われるので、それを避けたいと思います。

この良い例は、初めて起動したときの公式Twitterアプリで、友達リストから何人かの人を追加する手順を説明します。

Twitterアプリの提案ページのスクリーンショット。関連するセクションが強調表示されています

赤いセクションは私が達成したいものとほぼ同じであり、黄色のセクションは同じセクションのNSFetchedResultsControllerからの結果です(ただし、カスタムスタイルでは別のセクションになる場合があります)。

4

2 に答える 2

33

これはかなりクリーンな方法で行うことができます。

Appleのサンプルコードを使用する標準のNSFetchResultsControllerで設定された標準のテーブルビューから始めていると仮定します。

まず、2つのユーティリティ関数が必要です。

- (NSIndexPath *)mapIndexPathFromFetchResultsController:(NSIndexPath *)indexPath
{
    if (indexPath.section == 0)
        indexPath = [NSIndexPath indexPathForRow:indexPath.row+1 inSection:indexPath.section];

    return indexPath;
}

- (NSIndexPath *)mapIndexPathToFetchResultsController:(NSIndexPath *)indexPath
{
    if (indexPath.section == 0)
        indexPath = [NSIndexPath indexPathForRow:indexPath.row-1 inSection:indexPath.section];

    return indexPath;
}

これらはかなり自明であるはずです-フェッチされた結果コントローラーからのインデックスパスを使用してテーブルにアクセスする場合は余分な行を追加するか、逆の場合は削除する場合に対処するのに役立ちます。

次に、追加のセルを作成する必要があります。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"MyCellId";

    if (indexPath.section == 0 && indexPath.row == 0)
    {
        UITableViewCell *cell;
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];
        cell.selectionStyle = UITableViewCellSelectionStyleGray;
        cell.textLabel.text = NSLocalizedString(@"Extra cell text", nil);

        return cell;
    }

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];
    }

    [self configureCell:cell atIndexPath:indexPath];

    return cell;
}

正しく構成されていることを確認してください(configurecellは、フェッチ結果コントローラーからのセルに対してのみ呼び出されます)。

// the indexPath parameter here is the one for the table; ie. it's offset from the fetched result controller's indexes
- (void)configureCell:(SyncListViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    indexPath = [self mapIndexPathToFetchResultsController:indexPath];

    id *obj = [fetchedResultsController objectAtIndexPath:indexPath];
    <... perform normal cell setup ...>
}

そして、それが存在することをテーブルビューに伝えます。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSInteger numberOfRows = 0;

    if ([[fetchedResultsController sections] count] > 0) {
        id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
        numberOfRows = [sectionInfo numberOfObjects];
    }

    if (section == 0)
        numberOfRows++;

    return numberOfRows;
}

選択に応答します。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];

    if (indexPath.section == 0 && indexPath.row == 0)
    {
        [self doExtraAction];
        return;
    }

    ... deal with selection for other cells ...

次に、結果コントローラーから取得した更新を再マップします。

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
    UITableView *tableView = self.tableView;

    indexPath = [self mapIndexPathFromFetchResultsController:indexPath];
    newIndexPath = [self mapIndexPathFromFetchResultsController:newIndexPath];

    switch(type) {
        ... handle as normal ...
于 2012-08-09T07:42:05.480 に答える
3

複雑さについての懸念は理解していますが、実際には、(行0のコードを追加する以外に) numberOfRowsInSection:1を追加して1を追加するだけです。indexPath.rowcellForRowAtIndexPath:

別の解決策は、さらに面倒になるために非常に複雑である必要はありません。

そうは言っても、あなたが提案している「見出し」は、セクションヘッダーの典型的な候補であるように思われます。

于 2012-06-10T00:18:26.123 に答える