传递ManagedObjectContext以使用具有根UITabBarController的故事板来查看控制器

时间:2012-02-28 04:30:39

标签: core-data ios5 uinavigationcontroller uitabbarcontroller uistoryboard

使用故事板,您无法轻松访问appDelegate中的第一个视图控制器(尽管一旦执行prepareForSegue,就可以轻松地将ManagedObjectContext传递到导航堆栈中。

我决定给每个视图控制器(或每个视图控制器的超类)要求Core Data访问一个moc成员:

@synthesize moc = _moc;
@property (nonatomic) __weak NSManagedObjectContext *moc;

我对此感到不安,因为它似乎不是一种非常优雅的方式 - 代码太多了。但直接分配需要在viewControllers数组中指定绝对索引,并在每次ManagedObjectContexts的需求发生变化时更改appDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;

    // rootView gets a tab bar controller
    for(UINavigationController *navController in tabBarController.viewControllers) {

        for(UIViewController *viewController in navController.viewControllers) {

            if([viewController respondsToSelector:@selector(setMoc:)]) {
                [viewController performSelector:@selector(setMoc:) withObject:self.managedObjectContext];
                NSLog(@"Passed moc to %@", [viewController description]); 
            }
        }
    }

    return YES;
}

这种方法存在哪些缺陷,是否有更好的方法?尝试更通用是否更好:

- (void)assignManagedObjectContextIfResponds:(UIViewController *)viewController {

    if([viewController respondsToSelector:@selector(setMoc:)]) {
        [viewController performSelector:@selector(setMoc:) withObject:self.managedObjectContext];
        NSLog(@"Passed moc to %@", [viewController description]); 
    }

}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSMutableArray *viewControllers = [NSMutableArray array];

    UIViewController *firstLevelViewController = self.window.rootViewController;

    if([firstLevelViewController respondsToSelector:@selector(viewControllers)]) {

        NSArray *firstLevelViewControllers = [firstLevelViewController performSelector:@selector(viewControllers)];

        for(UIViewController *secondLevelViewController in firstLevelViewControllers) {

            if([secondLevelViewController respondsToSelector:@selector(viewControllers)]) {

                NSArray *secondLevelViewControllers = [secondLevelViewController performSelector:@selector(viewControllers)];

                for(UIViewController *thirdLevelViewController in secondLevelViewControllers) {

                    [viewControllers addObject:thirdLevelViewController];
                }

            } else {
                [viewControllers addObject:secondLevelViewController];
            }
        }
    } else {
        // this is the simple case, just one view controller as root
        [viewControllers addObject:firstLevelViewController];
    }

    // iterate over all the collected top-level view controllers and assign moc to them if they respond
    for(UIViewController *viewController in viewControllers) {
        [self assignManagedObjectContextIfResponds:viewController];
    }

    return YES;
}

2 个答案:

答案 0 :(得分:4)

不知道我是否理解正确,但为什么不直接在AppDelegate类中离开托管对象上下文并留下实例化的所有逻辑。从那以后你可以要求它。

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;

然后你可以随时随地回想起它。

NSManagedObjectContext *moc = [(YourApplicationDelegate*)[[UIApplication sharedApplication] delegate] managedObjectContext];

为方便起见,我宣布了一个定义:

#define MOC [(YourApplicationDelegate*)[[UIApplication sharedApplication] delegate] managedObjectContext]

因此,这成为:

[MOC save:&error];

你可以随心所欲地随身携带。 试着看一下Xcode中CoreData应用程序的自动生成代码,你会看到许多带有CoreData的访问器都在那里,并且CoreData本身在第一次请求时被懒惰地初始化。

答案 1 :(得分:2)

亚当,

虽然我正在探索故事板,但我几乎以同样的方式做到了这一点,除了我使每个具有MOC属性的视图控制器符合协议。

那里没有什么显着不同,所以我会继续前进。

我认为重点是故事板,IMO,都是半生不熟的。来自.Net背景显然缺少的是一个与IoC容器相连的对象构建器框架。 当Apple补充说Storyboard会很棒。当storyboard框架可以查看destinationViewController时,确定它的依赖关系并从容器生命中解析它们会很棒。现在,所有它真正能做的就是查看destinationViewController并初始化一个通用的,它的用途有限。

不幸的是,因为它是一个半生不熟的解决方案,我现在坚持使用传统的方法所以我的所有视图控制器都是手动分配和初始化的,更重要的是我为每个视图控制器添加了一个方法initWithMO​​C:(MOC *)moc;

我的架构师告诉我这段代码更强大,我想这是值得权衡的问题。

其他人想出更好的方法吗?

CA