4

J'ai une question d'architecture. Mon application utilise un TabBarController directement dans la fenêtre de l'application. Le composant ApplicationDelegate crée le managedObjectContext, bien qu'il n'en ait pas réellement besoin.Comment partager un ManagedObjectContext lors de l'utilisation de UITabBarController avec des contrôleurs UINavigationController internes

Chaque ViewController dans le TabBarController est un contrôleur de navigation. Le premier contrôleur de vue pour chaque NavigationController sont mes vues personnalisées. Tout est créé un lien via Interface Builder.

Maintenant, comment est-ce que je passe le managedObjectContext autour du bon chemin? En fait, j'ai besoin de mes vues pour charger les données dès que possible de sorte que lorsque l'utilisateur choisit un onglet ou navigue à travers les NavigationControllers, les données sont déjà là.

Mes questions sont les suivantes:

  1. Comment je passe le contexte correctement?
  2. Quand dois-je récupérer mes données, c'est-à-dire dans quelle méthode? "viewDidLoad" ou "viewDidAppear"?

Merci pour toutes les idées!

Répondre

9

Vous devez généralement éviter d'obtenir des objets partagés du délégué de l'application. Cela le fait trop se comporter comme une variable globale, et tout un tas de problèmes y sont associés. Et les singletons ne sont que des variables globales fantaisistes, elles devraient donc être évitées, sauf si elles sont réellement nécessaires.

Je voudrais ajouter une propriété managedObjectContext à chacun de vos contrôleurs de vue et l'affecter lorsque vous les créez. De cette façon, vos contrôleurs de vue n'ont pas de lien étroit avec le délégué de l'application. En ce qui concerne le moment d'aller chercher les données, vous devriez le faire paresseusement. Les données de base sont vraiment rapides, donc j'attendrais jusqu'à viewWillAppear: pour faire votre récupération. Si vous attendez jusqu'à viewDidAppear:, la vue est déjà à l'écran et il y aura un scintillement lors du chargement des données. Sachez toutefois que viewWillAppear: est appelée chaque fois que votre vue devient visible (par exemple, lorsque l'utilisateur appuie sur le bouton de retour de la barre de navigation ou qu'un contrôleur de vue modale est ignoré). Vous pouvez donc vérifier si vous avez déjà chargé les données et ignorer le chargement sur les appels suivants.

+0

Merci. Cela m'a aidé. – Czar

0

Vous pouvez l'obtenir auprès du délégué de l'application à tout moment comme celui-ci:

myApp *d = [[UIApplication sharedApplication] delegate]; 
NSManagedObjectContext *managedObjectContext = d.managedObjectContext; 

ou des variantes de ce qui précède. A part ça, vous pouvez ajouter une propriété à tous vos viewcontrollers et les transmettre ou vous pouvez créer un singleton et référencer cela globalement.

+0

Accès aux délégués d'applications managedObjectContext est en quelque sorte un singleton, non? – Czar

+0

est "managedObjectContext" une propriété à laquelle je peux toujours accéder? Ou dois-je jeter d'une manière ou d'une autre? – Czar

+0

Le pointeur de l'exemple est de type NSManagedObjectContext, donc pas besoin de lancer. – Ben

2

J'ai rencontré ce même problème, je vais partager ma solution.

D'abord vous avez besoin d'une référence au contrôleur de navigation dans la barre d'onglets dans le fichier nib, assurez-vous de le connecter.

IBOutlet UINavigationController *navigationController; 

Ensuite, obtenir le contrôleur comme recommandé dans la documentation de support et de lui envoyer le managedObjectContext:

SavedTableViewController *saved = (SavedTableViewController *)[navigationController topViewController]; 
saved.managedObjectContext = self.managedObjectContext; 

Alex a raison, « Vous devriez généralement rester à l'écart d'obtenir des objets partagés du délégué de l'application.Il fait se comporter trop comme une variable globale, et qui a un gâchis de problèmes qui y sont associés. »

0

Swift

Vous devriez pas partagent un NSManagedObjectContext, mais vous peut partager le NSPersistentStoreCoordinator

Ainsi, vous pouvez créer un nouveau contexte d'objet géré pour chaque vue, chacun partageant le même magasin.C'est la méthode préférée, et permet un accès simultané, multithreaded Dans l'exemple ci-dessous, je suppose que votre AppDelegate, * si créé avec une version récente de Xcode avec Utilisation de base de données vérifié *, a une propriété nommée persistentStoreCoordinator:

lazy var managedObjectContext:NSManagedObjectContext? = { 
    // This property is optional since there are legitimate error conditions that could cause the creation of the context to fail. 

    if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate { 
     let coordinator = appDelegate.persistentStoreCoordinator 
     var managedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType) 
     managedObjectContext.persistentStoreCoordinator = coordinator 
     return managedObjectContext 
    } 
    }()