配置tableview单元以将获取的对象传递到另一个视图(NSFetchedResultsController)

时间:2014-03-26 15:04:56

标签: ios objective-c uitableview core-data nsfetchedresultscontroller

编辑:发布大量更新以支持Mike A.的NSFetchedResultsController方法,请参阅以前{{​​1}}实施的修改历史记录。

我有一个简单的调查应用,其中包含多个NSFetchRequest -

ViewControllers

我的StartViewController InfoViewController Q1ViewController ... Q4ViewController EndViewController ResultsViewController DetailsViewController 创建了我的managedObject

InfoViewController

每个视图都有按钮和文本字段以及// Identify the app delegate MMUAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; // Use appDelegate object to identify managed object context NSManagedObjectContext *context = [appDelegate managedObjectContext]; // Create new managed object using the MMU entity description NSManagedObject *ManagedObjectMMU; ManagedObjectMMU = [NSEntityDescription insertNewObjectForEntityForName:@"MMU" inManagedObjectContext:context]; // Declare managed object self.ManagedObjectMMU = ManagedObjectMMU; 。当选择按钮或输入文本时,点击导航栏上的“下一步”按钮,每个值都会保存在我的navController中,如下所示:

managedObject

- (IBAction)nextBtnPressed:(UIButton *)sender { // error checks etc before [self.ManagedObjectMMU setValue:timeStamp forKeyPath:@"timeStamp"]; [self.ManagedObjectMMU setValue:timeStamp forKeyPath:@"name"]; [self.ManagedObjectMMU setValue:timeStamp forKeyPath:@"doB"]; // next viewcontroller pushed here } 会在每个视图中传递,直到它到达ManagedObjectMMU,并保存到ENDViewController

managedObjectContext

保存所有结果:

// Pass managed object to next ViewController
Q1.ManagedObjectMMU = self.ManagedObjectMMU;

我的模型非常基本,10个属性都是字符串类型。

Data Model

以下是完整提交的示例:

// Save managed object to managedObjectContext
NSError *error;
[[self.ManagedObjectMMU managedObjectContext] save:&error];

data: { dateOfBirth = "Sep 5, 1989"; gender = Male; name = Ross; q1 = "Computing, Mathematics & Digital Technology"; q2 = Yes; q3 = Football; q4 = "Commute From Home"; q5 = Bicycle; status = University; timeStamp = "3/26/14, 2:56 PM"; } 是所有结果的ResultsViewController,每个UITableView包含每次提交的cell.textLabel.textname包含cell.detailLabel.text }。我正在使用timeStamp从我的模型中获取结果(请参阅Mike A.的答案,我已经实现了他的方法)。

ResultsViewController

我想要发生的是当用户点击一个单元格时,带有该特定“名称”的获取结果对象将被传递到下一个视图,显示与该对象关联的数据(dataOfBirth,gender,q1,..等等)。

我的问题是:如何将已经获取的对象传递给下一个视图以显示该特定名称的所有对象?我可以在另一个NSFetchedResultsController上显示这些指定的对象,还是应该创建一些UITableViewUITextFields来显示结果?我应该在Labels方法中传递提取的对象,还是应该实现tableView:didSelectRowAtIndexPath:?很抱歉,如果这是一个简单的解决方案,我已经在网上搜索了几天,但找不到合适的解决方案!感谢。

更新:

感谢Mike A的建议和代码片段,我使用以下代码实现了解决方案:

prepareForSegue

DetailView只是有一些文本字段和标签来显示从单元格传递的对象的问题和适当的提交:

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
    }

    // Configure the cell...
    [self configureCell:cell atIndexPath:indexPath];

    return cell;
}

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    MMU *results = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = results.name;
    cell.detailTextLabel.text = results.timeStamp;

}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    DetailViewController *detailView = [[DetailViewController alloc]initWithNibName:@"DetailViewController" bundle:nil];

    // Pass fetched object to next ViewController
    detailView.ManagedObjectMMU = [self.fetchedResultsController objectAtIndexPath:indexPath];

    // Push the view controller.
    [self.navigationController pushViewController:detailView animated:YES];
}

如果没有Mike A,我无法做到,如果您想了解解决方案,请仔细阅读他的回答和下面的评论!

1 个答案:

答案 0 :(得分:2)

我建议在每个视图控制器中使用NSFetchedResultsController。这样您就不必在每个视图控制器中处理数组,只需获取请求。我不建议在App Delegate中创建它们。最好在每个视图控制器或类别中。

因此,在视图控制器中尝试为NSFetchedResultsController创建属性并实现其getter。

NSFetchedResultsController示例

@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;


- (NSFetchedResultsController *)fetchedResultsController
{
    if (!_fetchedResultsController) {

        _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:[self fetchRequest]
                                                                        managedObjectContext<# your managedObjectContext #>
                                                                          sectionNameKeyPath:nil
                                                                                   cacheName:nil];

        self.fetchedResultsController.delegate = self;

        NSError *error = nil;
        if (![self.fetchedResultsController performFetch:&error]) {
            NSLog(@"Error: %@ %@", error.localizedDescription, error.userInfo);
        }
    }

    return _fetchedResultsController;
}

并为您的获取请求实现一种方法:

- (NSFetchRequest *)fetchRequest
{
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"MMU"];

    // predicates, sort descriptors and other options go here...

    return fetchRequest
}

然后您可以使用

更新tableview数据源
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return self.fetchedResultsController.fetchedObjects.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
    }

    MMU *results = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = [NSString stringWithFormat:@"%@ ",results.name]; // Consider results.name without stringWithFormat.
    cell.detailTextLabel.text = [NSString stringWithFormat:@"%@ ", results.timeStamp];

    return cell;
}

现在,在设置了这样的视图控制器之后,在触摸或在某处放置文本时更新模型。在下一个视图控制器中,您可以设置新的提取结果控制器和新的提取请求,请求已经更改的数据。

根据您拥有的视图控制器的数量,更好的方法是将UITableViewController子类化为默认情况下实现获取的结果控制器,并且每次都更改获取请求。

如果这没有帮助,请提供有关如何展示新视图控制器以及如何更新模型的更多信息。

更新

您可以通过实施prepareForSegue:tableView:didSelectRowAtIndexPath:将每个对象从视图控制器传递到视图控制器。在这种情况下,您必须在头文件中为要传递对象的每个视图控制器声明一个公共属性。请注意,实现这些方法后,您将通过点击单元格而不是示例中提供的IBAction导航到下一个视图控制器。

如果使用segues推送视图控制器,可以使用以下示例。

prepareForSegue:示例

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{
   [super prepareForSegue:segue sender:sender];

   UIViewController *nextViewController = segue.destinationViewController;
   nextViewController.mmuModel = self.mmuModel; // The initial model that you have from InfoViewController.
}

此方法将与下一个视图控制器共享您的mmuModel。但是,您需要单独更新每个视图控制器中的模型。

这将完成工作,但CoreData并不打算以这种方式使用。 CoreData是一个强大的框架,通常会为您提供很多东西。另一种方法是在NSManagedObject中创建一个新的InfoViewController,而不是在问题视图控制器中传递托管对象,每次使用NSFetchedResultsController时都可以获取它,就像我展示的那样您。只有这次你必须找到一种过滤结果的方法,这样你才能得到你想要的对象。有多种方法可以做到这一点,一种方法是使用某种id和谓词。

此外,在您的数据模型中,不要将所有内容都放在一个实体(MMU)中,而应考虑分离一些内容并使用关系。

对于您的属性,不同的数据类型也是一个很好的例子,即timeStamp应该是Date,如果唯一的选项是男性,女性等,性别可以是BOOL。

我希望这有点帮助。如果您仍然遇到问题,请告诉我。