Korzystanie storyboardy nie masz łatwy dostęp do pierwszego kontrolera widok w appDelegate (choć raz zrobisz prepareForSegue
ułatwia przekazać ManagedObjectContext dół stosu nawigacji.Przechodząc ManagedObjectContext aby kontrolery za pomocą storyboardy z UITabBarController korzenia
mam rozliczone dając każdego kontrolera widoku (lub nadklasą każdego kontrolera widoku) wymagających dostępu do danych Rdzeń MOC użytkownika:
@synthesize moc = _moc;
@property (nonatomic) __weak NSManagedObjectContext *moc;
jestem niespokojny o tym, ponieważ nie wydaje się bardzo elegancki sposób to zrobić to - za dużo kodu, ale przypisanie bezpośrednio wymaga podania absolutnego indeksu XES do tablic viewControllers i za każdym razem zmieniając appDelegate wymóg ManagedObjectContexts zmienić
- (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;
}
Jakie są pułapki tego podejścia i czy istnieje lepszy sposób? Czy lepiej jest spróbować i być bardziej ogólna:
- (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;
}
Wiem, że możesz to zrobić, ale staram się tego uniknąć. Nie potrafię jednoznacznie określić, dlaczego jest źle, ale tak to wygląda, #importuje AppDelegate wszędzie. –
Nie jest źle, to jest sposób postępowania, nie ma sensu przekraczanie kontekstu, kiedy można łatwo uzyskać do niego dostęp. Import jest potrzebny tylko w celu uniknięcia ostrzeżenia kompilatora (nie błędu), ponieważ za każdym razem, gdy można wywołać [UIApplication sharedApplication] z dowolnego miejsca w kodzie i będzie działać w odniesieniu do importu, to jest to, co Xcode generuje dla aplikacji CoreData, to zadziwia mi, dlaczego twierdzisz, że to źle, i wolą przekazać kontekst w taki sposób. Dzięki scentralizowaniu akcesorów CoreData zyskujesz także większą kontrolę nad błędem zapisu, leniwym ładowaniem, cokolwiek chcesz. – Leonardo
http://cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html "wrong" może nie było właściwym słowem. Szukam optymalnego. –