6

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; 
} 

Odpowiedz

2

Adam

Podczas gdy ja odkrywania storyboardy I dość dużo zrobił to w ten sam sposób co zrobiłeś z wyjątkiem Zrobiłem moim zdaniem każdy z kontrolerów, które miały właściwości MOC zgodne z protokołem.

Nie ma w tym nic istotnego, więc pójdę dalej.

Myślę, że chodzi o to, że Storyboardy, IMO, są na pół upieczone. Pochodzący z tła .Net, którego oczywiście brakuje, to framework do budowania obiektów połączony z kontenerem IoC. Gdy Apple doda, że ​​Storyboard będzie niesamowite. Gdy struktura storyboardów może spojrzeć na obiekt docelowyViewController, określić jego zależności i rozwiązać te z życia kontenera będzie świetnie. Na razie wystarczy tylko spojrzeć na obiekt docelowyViewController i zainicjować ogólny, który ma ograniczone zastosowanie.

Niestety, ponieważ jest to niedopieczone rozwiązanie, na razie trzymam się tradycyjnego podejścia, więc wszystkie moje kontrolery widoku są przydzielane i inicjowane ręcznie, a co ważniejsze, dodałem metodę do każdego kontrolera widoku do initWithMOC: (MOC *) moc;

Architekt, który mi powiedział, mówi, że ten kod jest bardziej niezawodny, wydaje mi się, że jest to kwestia opinii, czy warto go wymieniać.

Ktoś inny wymyślić lepszy sposób?

CA.

4

Nie wiem, czy prawidłowo zrozumiałem, ale dlaczego nie opuścił kontekst obiektu zarządzanego bezpośrednio w klasie AppDelegate i zostawić wszystkie logiki dla instancji. Od tego czasu możesz o to poprosić.

to można go przywołać w dowolnym momencie z dowolnego miejsca.

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

Dla wygody oświadczyłem definiowania dla niego:

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

Dlatego to stać:

[MOC save:&error]; 

Można wziąć to wszędzie chcesz. Po prostu spróbuj rzucić okiem na wygenerowany automatycznie kod dla aplikacji CoreData w Xcode, zobaczysz, że jest tam wiele akcesorów z CoreData, a sama CoreData jest leniwie inicjowana na pierwsze żądanie.

+1

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. –

+1

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

+0

http://cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html "wrong" może nie było właściwym słowem. Szukam optymalnego. –