【问题标题】:Core Data, UITableView, and UISegmentedControl核心数据、UITableView 和 UISegmentedControl
【发布时间】:2010-08-04 03:41:58
【问题描述】:

我是使用 Core Data 的新手,并且正在使用 UITableView。我有一个带有 UISegmentedController 的工具栏,我想根据所选索引过滤 UITableView 中的项目。换句话说,假设我有一个 UITableView 来显示 Books(存储在 Core Data 中)和一个 UISegmentedController 用段来显示“English”、“Spanish”和“French”的书。

这里有什么方法可以让所有东西都连接起来?当点击其中一个段时,我在 UISegmentedControl 的目标中做什么来改变周围的东西?

对不起,如果这是一个愚蠢的问题!

【问题讨论】:

    标签: iphone objective-c core-data


    【解决方案1】:

    我会为每个段使用一个单独的 NSFetchedResultsController。这将允许您利用每个段的内置缓存并提高性能。

    除了 Apple 的文档(和我的书)之外,您还可以阅读我在 PragPub 杂志上的文章 Touching The Core

    【讨论】:

    • 我不禁要说,作为已经为社区付出了这么多的人,我非常惊讶你花时间回答我关于 SO 的问题。一百万谢谢!
    • Marcus,最干净的实现方式是什么?如果您有三个段,这将需要三个 FRC,并且在 tableview 代码中包含所有这些 switch() case: 语句并不是很漂亮。也许创建一个typedef enum,其标签对应于各个段,然后将 FRC 添加到类中适当索引处的 NSArray 中?然后你所要做的就是引用[self.frcArray objectAtIndex:[segControl selectedSegmentIndex]] 之类的东西,否则会有switch() case。还是有更清洁的方法?
    • 将它们作为 iVar 并拥有 currentFRC iVar。当点击分段控件时,您切换currentFRC 指向的内容并告诉tableView 重新加载。其他所有内容都与currentFRC 对话,并检查您的委托方法,以便它们忽略任何不是来自currentFRC 的消息。
    【解决方案2】:

    为每个过滤器使用三个不同的数组是个好主意。将它们缓存在某处,以便在用户选择过滤器时不会延迟。要从 CoreData 存储中查找您要查找的信息,请使用 NSPredicate。

    【讨论】:

    • 在 Core Data 中使用数组的代码比您需要编写的要多。最好使用NSFetchedResultsController,因为这是它的设计目的。
    • 适当指出:我特别喜欢 NSFetchedResultsController 使用某种缓存。我的大部分数据都是动态的,所以我想我认为大多数事情都在 NSMutableArrays 中
    • 即使是动态数据,带有内存存储和NSFetchedResultsController 的Core Data 在几乎所有情况下都会减少代码并提高性能。值得深思。
    【解决方案3】:

    您可以使用NSFetchedResultsController,当您单击段时,只需设置不同的谓词并再次执行获取。

    【讨论】:

    【解决方案4】:

    我已经使用上述 Marcus 的指南实现了这一点(我是新手,所以它可能不是最好的方法)。我有一个分段控制器,其中包含“打开”、“进行中”和“关闭”三个选项。

    在 ViewController.h 中,为每个段选项创建一个 iVar,并为将存储当前控制器的主控制器创建一个 iVar。

    @property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
    
    @property (nonatomic, retain) NSFetchedResultsController *inprogressFetchedResultsController;
    @property (nonatomic, retain) NSFetchedResultsController *openFetchedResultsController;
    @property (nonatomic, retain) NSFetchedResultsController *closedFetchedResultsController;
    

    在 ViewController.m 中你需要创建延迟加载这些控制器的方法,所以我一共有三个。除了谓词和缓存名之外,它们基本相同,我在下面只展示了一个。

    - (NSFetchedResultsController *)closedFetchedResultsController
    {
        if (_closedFetchedResultsController != nil) {
            return _closedFetchedResultsController;
        }
    
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    
        // Edit the entity name as appropriate.
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"Ticket" inManagedObjectContext:self.managedObjectContext];
        [fetchRequest setEntity:entity];
    
        // Set the batch size to a suitable number.
        [fetchRequest setFetchBatchSize:20];
    
        // Edit the sort key as appropriate.
        NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"priority.name" ascending:NO];
        NSArray *sortDescriptors = @[sortDescriptor];
    
        [fetchRequest setSortDescriptors:sortDescriptors];
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"status = 'Closed'"];
        [fetchRequest setPredicate:predicate];
    
        NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"priority.name" cacheName:@"ClosedTickets"];
        aFetchedResultsController.delegate = self;
    
        self.closedFetchedResultsController = aFetchedResultsController;
    
        NSError *error = nil;
        if (![self.closedFetchedResultsController performFetch:&error]) {
            // Replace this implementation with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    
        return _closedFetchedResultsController;
    }
    

    为您的段创建一个 IBAction,以便在更改时更改获取的结果控制器并重新加载表。

    - (IBAction)statusChanged:(id)sender {
        switch (self.segmentControl.selectedSegmentIndex) {
            case 0:
                self.fetchedResultsController = self.inprogressFetchedResultsController;
                break;
            case 1:
                self.fetchedResultsController = self.openFetchedResultsController;
                break;
            case 2:
                self.fetchedResultsController = self.closedFetchedResultsController;
                break;
            default:
                break;
    
        }
        [self.tableView reloadData];
    }
    

    就是这样!

    注意我还将这一行添加到我的 ViewDidLoad 方法中,以便它最初将正确的选项加载到 fetchedResultsController 中。

    self.fetchedResultsController = self.inprogressFetchedResultsController;
    

    【讨论】:

      猜你喜欢
      • 2012-09-15
      • 1970-01-01
      • 1970-01-01
      • 2012-01-29
      • 2013-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多