iOS Core Data - 将上下文传递给详细视图的设计模式

Posted

技术标签:

【中文标题】iOS Core Data - 将上下文传递给详细视图的设计模式【英文标题】:iOS Core Data - Design Pattern for Passing Context to Detail Views 【发布时间】:2010-10-27 04:27:25 【问题描述】:

我对一个我认为可以追溯到我的设计的问题感到有些困惑。

我正在基于一组主要静态的行 (4) 构建一个 TableViewController - 使用它作为 UITableView 的基础。每一行都会启动不同的视图(详细信息和 UITableViews)......在我的顶视图的托管对象上下文中,我可以轻松导航到关联的详细视图,因为它在上下文中(昵称).. 我最初只是想拥有不相关的表格和一系列会触发视图的按钮......但我放弃了这个想法。我当前的主要问题是知道如何切换 MOC 或不同的 fetchedresults 控制器(通过在每个 .m 中定义的方式从不同的表中获取。

目前,我在 TableViewControler.m 中有一个开关。这个片段有效:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
    NSInteger switchval = indexPath.row;

    switch (switchval) 
     case 0: // Nickname 
     
       //This version brings up a detailed view controller - 
      NickNameDetail *controller = [[NickNameDetail alloc] initWithNibName:@"NickNameDetail" bundle:nil];
      controller.fetchedResultsController = self.fetchedResultsController;
      controller.managedObjectContext = [self.fetchedResultsController objectAtIndexPath:indexPath];
      [self.navigationController pushViewController:controller animated:YES];
      break;  
     
     case 1:  
           
      //NextTableViewContoller *.... (etc)... here here
    ...

但是,我不知道如何切换到不同的上下文并获取不同的行。

meTableViewController.managedObjectContext = self.managedObjectContext;
nickNameDetail.managedObjectContext = self.managedObjectContext;
nextTableViewController.managedObjectContext = self.managedObjectContext;

以前有人遇到过这样的情况吗?抱歉,无法让代码格式化程序正常运行。

谢谢!

【问题讨论】:

【参考方案1】:

在某些情况下,将当前视图控制器的 MOC 传递给推送到导航堆栈上的新视图控制器可能是好的/合适的。但是,您通常希望传递一个新创建的 MOC。请按如下方式执行:

在您的应用委托中添加以下方法

- (NSManagedObjectContext*)createNewManagedObjectContext


    NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init]; 
    [moc setPersistentStoreCoordinator:[self persistentStoreCoordinator]]; 
    return [moc autorelease];

在您的视图控制器中按如下方式传递 MOC

myAppDelegate *mainDelegate = (myAppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *mainMOC = [mainDelegate createNewManagedObjectContext]; 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSave:) 
                                                         name:NSManagedObjectContextDidSaveNotification
                                                       object:mainMOC];

newViewController.managedObjectContext = mainMOC;

然后根据需要处理通知,这里是一个例子

- (void)contextDidSave:(NSNotification *)notification


    [managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
    [self.tableView reloadData];


您还需要为每个视图控制器定义和使用不同的 NSFetchedResultsController。这是因为对于每个视图控制器(不同的实体、谓词等),您要获取和显示的数据当然是不同的。只需在每个实现文件中定义它们。这是一个例子:

- (NSFetchedResultsController *)fetchedResultsController 

    if (fetchedResultsController != nil) 
        return fetchedResultsController;
    

    /*
     Set up the fetched results controller.
     */

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Context" inManagedObjectContext:managedObjectContext];
    [request setEntity:entity];

    if(self.project)
        // get the contexts for the project
        NSPredicate * predicate = [NSPredicate predicateWithFormat: @"projectName == %@", self.project.name];
        [request setPredicate:predicate];
    

    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [request setSortDescriptors:sortDescriptors];


    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    [aFetchedResultsController release];
    [request release];
    [sortDescriptor release];
    [sortDescriptors release];

    return fetchedResultsController;
    

然后根据需要使用 fetchedResultsController。例如,把它放在你的 viewDidLoad 方法中:

    NSError *error;
    if (![[self fetchedResultsController] performFetch:&error]) 
        // Handle error
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    

【讨论】:

非常感谢!我会试试这个。它在各个层面上都有意义。对不起,我的回复晚了,我的偏好中的电子邮件通知似乎不起作用...... 好吧,如果您喜欢这个答案,请考虑投票;-) 您好,不可原谅,这种方法实际上效果很好。我只是将它连接起来,只收到 2 个警告:(1)“mainDelegate”的本地声明隐藏了实例变量(2)“myAppDelegate”可能不响应“-createNewManagedObjectContext”。我将深入研究该分析,但我必须说,我印象深刻! 我有兴趣了解与整个项目谓词相关的这篇文章。在此之前我没有任何谓词,但在我得到它之后毫无疑问。 if(self.project) // 获取项目的上下文 NSPredicate * predicate = [NSPredicate predicateWithFormat: @"projectName == %@", self.project.name]; [请求集合谓词:谓词]; .... 你肯定得到了我的回答!非常感谢您! :) 解决警告: 1) 将 mainDelegate 更改为不同的东西(例如 myDelegate),因为您已经有一个名为 mainDelegate 的变量; 2)在您的应用程序委托的头文件中添加方法 - (NSManagedObjectContext*)createNewManagedObjectContext;

以上是关于iOS Core Data - 将上下文传递给详细视图的设计模式的主要内容,如果未能解决你的问题,请参考以下文章

如何将参数传递给 Core Data 生命周期方法?

如何将多个参数传递给 ASP.NET CORE MVC 中的 HttpGet 方法?

如何将表单视图作为 django 中的上下文传递给另一个视图?

ios/xcode/core data:更新屏幕的最佳方式

IOS/Swift:将表视图中的对象传递给详细视图控制器

如何将多个参数传递给 ASP.NET Core 中的 get 方法