Passage de ManagedObjectContext pour afficher les contrôleurs à l'aide de storyboards avec un UITabBarController racine

StackOverflow https://stackoverflow.com/questions/9476420

Question

En utilisant des storyboards, vous n'avez pas d'accès facile au premier contrôleur de vue dans appDelegate (bien qu'une fois que vous l'avez fait prepareForSegue facilite la transmission du ManagedObjectContext dans la pile de navigation.

J'ai décidé de donner à chaque contrôleur de vue (ou superclasse de chaque contrôleur de vue) nécessitant un accès à Core Data un membre moc :

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

Cela me met mal à l'aise car cela ne semble pas être une façon très élégante de le faire - trop de code.Mais l'attribution directe nécessite de spécifier des index absolus dans les tableaux viewControllers et de modifier appDelegate à chaque fois que l'exigence de ManagedObjectContexts change.

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

Quels sont les pièges de cette approche et existe-t-il une meilleure solution ?Vaut-il mieux essayer d'être plus générique :

- (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;
}
Était-ce utile?

La solution

Adam,

Pendant que j'explorais les storyboards, je l'ai fait à peu près de la même manière que vous, sauf que j'ai rendu chacun de mes contrôleurs de vue doté d'une propriété MOC conforme à un protocole.

Il n’y a rien de très différent là-bas, alors je vais passer à autre chose.

Je pense que le fait est que les storyboards, à mon avis, sont à moitié cuits.Venant d'un arrière-plan .Net, ce qui manque évidemment, c'est un framework de création d'objets couplé à un conteneur IoC.Quand Apple ajoutera que les storyboards seront géniaux.Lorsque le framework de storyboard peut examiner le destinationViewController, déterminer ses dépendances et résoudre celles de la vie d'un conteneur sera formidable.Pour l'instant, tout ce qu'il peut réellement faire est de regarder le destinationViewController et de vous en lancer un générique, qui est d'une utilité limitée.

Malheureusement, comme il s'agit d'une solution à moitié cuite, je m'en tiens à l'approche traditionnelle pour l'instant, donc tous mes contrôleurs de vue sont alloués et initialisés manuellement et, plus important encore, j'ai ajouté une méthode à chaque contrôleur de vue pour initWithMOC :( MOC *)moc;

L'architecte en moi me dit que ce code est plus robuste, je suppose que c'est une question d'opinion quant à savoir si le compromis en vaut la peine.

Quelqu'un d'autre a-t-il une meilleure solution ?

CALIFORNIE.

Autres conseils

Je ne sais pas si j'ai bien compris, mais pourquoi ne laissez-vous pas le contexte de l'objet géré directement dans la classe AppDelegate et n'y laissez-vous pas toute la logique d'instanciation.Et à partir de là, vous pourrez le demander.

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

alors vous pouvez le rappeler à tout moment et de n'importe où.

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

Pour plus de commodité, j'ai déclaré une définition :

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

Cela devient donc :

[MOC save:&error];

Vous pouvez l'emporter partout où vous le souhaitez.Essayez simplement de jeter un œil au code généré automatiquement pour une application CoreData dans Xcode, vous verrez que de nombreux accesseurs avec CoreData s'y trouvent et que CoreData lui-même est initialisé paresseusement à la première demande.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top