如何通过 managedObjectContext 使用情节提要来初始化下一个控制器
Posted
技术标签:
【中文标题】如何通过 managedObjectContext 使用情节提要来初始化下一个控制器【英文标题】:How do I pass the managedObjectContext to init the next controller using storyboard 【发布时间】:2014-08-06 08:29:20 【问题描述】:我有这段代码可以跳转到第二个故事板
UIStoryboard *secondStoryBoard = [UIStoryboard storyboardWithName:@"SpaceView" bundle:nil];
// Load the initial view controller from the storyboard.
NRGSpacesNavController *nav = [secondStoryBoard instantiateInitialViewController];
nav.managedObjectContext = self.managedObjectContext;
NRGSpacesViewController *spacesController = [nav.viewControllers firstObject];
spacesController.space = space;
[self presentViewController:nav animated:YES completion:nil];
问题是在第二个情节提要上实例化的控制器需要 managedObejectContext 用于它的容器视图。在 prepareForSegue 之前加载的唯一内容是实际的 init 方法。但我似乎可以在 init 方法上添加上下文。 ViewDidLoad 和其他任何事情实际上都为时已晚。如果可以的话,我想保留故事板,但可以以编程方式做所有事情
我尝试将上下文添加到 nag 控制器,但它不起作用。上下文为零。
感谢您的帮助,欢迎提出任何想法。
【问题讨论】:
所以你使用了prepare for segue,遇到了问题? 为什么不对 managedObjectContext 使用单例? 【参考方案1】:在您要移动到的UIViewController
上创建一个属性,然后在prepareForSegue:
中设置该属性
在为过渡提供动力的UIViewController
中:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
if ([segue.identifier isEqualToString:@"YourVCSegue"])
NextViewController *nextVC = segue.destinationViewController;
nextVC.myManagedObjectContext = self.managedObjectContext;
在UIViewController
界面中被转换为:
@interface NextViewController : UIViewController
@property (nonatomic,strong) NSManagedObjectContext *myManagedObjectContext;
@end
这将在调用 init
方法之后(必须调用该方法,否则您将在 nil 对象上设置)和调用 viewDidLoad
之前设置属性。
另一个选项(不推荐)是创建一个包含 NSManagedObjectContext 的 Singleton 助手类,您可以在整个应用程序中访问它。例如:
[[MyCoreDataHelperClass sharedInstance] managedObjectContext];
有关在您的应用中访问 NSManagedObjectContext 的信息,请参阅documentation.
【讨论】:
将上下文传递给下一个视图控制器是这样做的首选方式,而不是单例或应用程序委托。来自 ios 5 Core Data 发布说明:“比以往任何时候都重要的是,您采用“传递接力棒”的方法来访问上下文(通过将上下文从一个视图控制器传递到下一个视图控制器),而不是直接从应用程序委托中检索它。 "这在文档的其他地方也有介绍,这也是 Apple 的模板代码所做的。 相应地更新了最新文档的链接。 来自同一个文档:“但有时,从应用程序、文档或视图控制器以外的地方检索上下文更容易或更合适。” 事实上,我总是发现从其他地方检索上下文更容易。如果我没记错的话,传递上下文与子上下文有关。 @SwapnilLuktuke 你已经断章取义了。之后明确指出,当您使用 NSFetchedResultsController 或 NSObjectController 或类似时,可以考虑这一点。【参考方案2】:您可以在 prepareForSegue 方法中将内容分配给即将到来的视图控制器。但是视图控制器实际上是存储上下文的不好的地方。 (导航控制器是一个视图控制器)。
更好的方法是将托管对象上下文创建为单例,或者有一个单独的类来处理所有核心数据交互并在该类中创建上下文。编写一个 getter 来获取上下文。
【讨论】:
【参考方案3】:好的,我在这里得到了修复。
// Load the initial view controller from the storyboard.
NRGSpacesNavController *nav = [secondStoryBoard instantiateInitialViewController];
NRGSpacesViewController *spacesController = [nav.viewControllers firstObject];
spacesController.space = space;
spacesController.managedObjectContext = self.managedObjectContext;
[self presentViewController:nav animated:YES completion:nil];
我似乎弄错了加载顺序。我还移动了一些东西来设置上下文属性。 此代码首先运行,然后是容器(在 spacesController 内)viewDidLoad,然后是 spacesController viewDidLoad。所以我将我的东西加载到那些 viewDidLoads 中,并且我使用一个委托来让容器知道包含的内容何时加载他们的视图。
【讨论】:
【参考方案4】:尽管有些人可能会发现这种反模式,但我倾向于拥有一个独特的 CoreDataController,它管理上下文的创建和共享。我从不喜欢传递上下文的想法,尤其是在多线程环境中。
话虽如此,我会使用以下解决方案之一:
i) 创建一个带有 NSManagedObjectContext 属性的协议,并让所有相关的控制器实现它。
@protocol MyProtocol
@property(nonatomic,strong) NSManagedObjectContext mySharedContext;
@end
ii) 如果应用程序是向下钻取接口并且不涉及繁重的多线程,即列表和详细信息,我将使用相同的协议方法,但声明一个通用的 NSManagedObject 可以从中检索上下文。
@protocol MyProtocol
@property(nonatomic,strong) NSManagedObject myObject;
@end
然后在目标控制器中
-(void)myMethod
// optional casting
MyParticularManagedObject *obj = (MyParticularManagedObject*)self.myObject;
NSManagedObjectContext *ctx = obj.managedObjectContext;
// rest of the code....
iii) 作为最后一点,看看这是否可能是您的情况:
prepareForSegue is not called after performSegue:withIdentifier: with popover style
【讨论】:
感谢您的评论,我实际上使用的是 CoreDataTableViewController,它实际上是通过加载另一个故事板来呈现 NextController。问题如下所示。 NextController 具有需要上下文的容器控制器。我看不出获得另一个上下文的意义。在我看来它并不干净。我将不得不使用 ObjectID 来查看它,我可以重新获取对象并使用 NextViewController 中的第二个上下文对其进行修改。顺便说一句,我还有一个设置 coreDataStack 的类,因此很容易实例化另一个上下文。 具有讽刺意味的是,它可以通过一个导航控制器来解决,但我在动画方面遇到了一些问题。我希望它不在第一个视图上显示导航栏,然后进行第二次向下钻取并显示它。但是当我回去时,它真的会再次隐藏导航栏。也许是自定义过渡?以上是关于如何通过 managedObjectContext 使用情节提要来初始化下一个控制器的主要内容,如果未能解决你的问题,请参考以下文章
如何观察 NSManagedObject 是不是从 managedObjectContext 中移除
如何从 ManagedObjectContext 中删除给定实体的所有对象
如何将 ManagedObjectContext 与线程一起使用
如何使用 managedObjectContext 来使用实体?