如何使用storyboard传递managedObjectContext以初始化下一个控制器

时间:2014-08-06 08:29:20

标签: ios objective-c cocoa-touch core-data

我有这个代码跳转到第二个故事板

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控制器,因为它可以做到它不起作用。上下文为零。

感谢您的帮助,欢迎任何想法。

4 个答案:

答案 0 :(得分: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帮助器类,您可以在整个应用程序中访问它。 E.g:

[[MyCoreDataHelperClass sharedInstance] managedObjectContext];

有关访问应用中NSManagedObjectContext的信息,请参阅documentation.

答案 1 :(得分:0)

您可以在prepareForSegue方法中为即将到来的视图控制器分配内容。但是视图控制器实际上是存储上下文的不好的地方。 (导航控制器是视图控制器)。

更好的方法是将托管对象上下文创建为单例,或者使用单独的类来处理所有核心数据交互并在该类中创建上下文。写一个getter来获取上下文。

答案 2 :(得分:0)

好的,我在这里得到了解决方案。

  // 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中加载我的东西,并且我使用委托让容器知道包含何时加载它们的视图。

答案 3 :(得分:-1)

Altough可能会发现这种反模式,我倾向于拥有一个独特的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