J'ai suivi les guides et les didacticiels Apple Developer et j'ai étudié deux livres pour iPhone sur le sujet des données de base.Définition d'un attribut sur une entité et récupération de celle-ci avec des relations "un-à-plusieurs"
Je suis habitué à manipuler le côté "objet de valeur"/"entité" des choses et à les envoyer ensuite à un service web ou à des goûts similaires. Mais sur l'iPhone je reçois tout gérer moi-même ... monde cruel :)
Les Locations
, TaggedLocations
et PhotoLocations
exemples à partir du site Apple Developer ne me donne pas les réponses d'une manière que je peux « calculer ». J'espère que quelqu'un ici peut m'éclairer.
J'ai configuré mon modèle en utilisant l'interface graphique du modèle de données. deux entités, Person
et Dream
. Person
a un attribut de chaîne personName
et une relation un-à-plusieurs dreams
. Dreams
a un attribut de chaîne description
et une relation un-à-un person
.
J'ai mis en place une application simple tableView
. Première vue est une liste de personnes et la deuxième vue est une liste de leurs rêves.
Voici comment ajouter une personne à l'modelObjectContext
:
Person *newPerson = (Person *)[NSEntityDescription
insertNewObjectForEntityForName:@"Person"
inManagedObjectContext:managedObjectContext];
[newPerson setPersonName:@"Ben Hur"];
OK, je puis ajouter un nouveau rêve dans le contexte:
Dream *newDream = (Dream *)[NSEntityDescription
insertNewObjectForEntityForName:@"Dream"
inManagedObjectContext:managedObjectContext];
[newDream setDescription:@"I had a nightmare"];
ajouter maintenant le rêve à la personne comme ceci:
[newPerson addDreamObject:newDream];
Ici, il devient un peu brumeux pour moi, car xcode a généré différentes méthodes/accesseurs pour moi sur la Person
Classe:
@class Dream;
@interface Person : NSManagedObject
{
}
@property (nonatomic, retain) NSString * personName;
@property (nonatomic, retain) NSSet* dream;
@end
@interface Person (CoreDataGeneratedAccessors)
- (void)addDreamObject:(Dream *)value;
- (void)removeDreamObject:(Dream *)value;
- (void)addDream:(NSSet *)value;
- (void)removeDream:(NSSet *)value;
@end
Dans d'autres situations, où je ne dois gérer l'économie réelle, la récupération, les données. J'aurais construit un objet entité/valeur appelé person
et lui ai donné un Array
pour stocker les rêves. Mais ce n'est pas un type d'attribut possible dans les données de base, et pas la façon de le faire, j'ai lu (ici aussi dans des threads similaires).
Alors, comment ce code passe-partout fonctionne-t-il? Suis-je censé utiliser le addDream
et lui envoyer un NSSet
rempli de rêves? ou puis-je juste faire confiance aux données de base pour instancier cela et utiliser exclusivement le addDreamObject
envoyer les objets entité Person
de type Dreams
? Je sauvegarde aussi le contexte en utilisant le code de xcode. Maintenant, je souhaite mettre à jour la vue avec cette personne, plus précisément son nom.
Dans la méthode cellForRowAtIndexPath
Je lui donne ceci:
NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [[managedObject valueForKey:@"personName"] description];
Encore une fois tout va bien et le nom est affiché sur la liste.
J'ai configuré mon DreamViewController
pour prendre en paramètre un objet Person
.
Person *selectedObject = [[self fetchedResultsController] objectAtIndexPath:indexPath];
dreamView.selectedPerson = selectedObject;
Puis je pousse le viewController
sur la pile et nous entrons dans le DreamView
. Ici, je n'arrive pas à atteindre les rêves liés à la personne que j'ai "envoyé" avec la vue.
C'est ce que je suis en train dans la méthode de viewDidLoad
DreamViewController
(selectedPerson
est l'accesseur que j'utilise pour passer l'objet Person
):
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"One Person";
NSManagedObjectContext *context = selectedPerson.managedObjectContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Dream"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError *error;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
// Handle the error.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
NSMutableArray *mutableArray = [fetchedObjects mutableCopy];
self.dreamArray = mutableArray;
NSLog(@"the length of dreamArray: %i",[self.dreamArray count]);
Dream *d = [dreamArray objectAtIndex:0];
NSLog(@"The Dream object says: %@", [d description]);
[mutableArray release];
[fetchRequest release];
}
Je ne peux pas sembler obtenir le coup de Ceci et mon expérience actuelle avec Objective C ne me permettent pas de saisir l'essence des «meilleures pratiques» entre les lignes de la documentation d'Apple.
Merci :) C'était très utile. J'ai pris quelques heures et j'ai relu les simples exemples «une entité» de ma documentation sur les livres et les pommes. Ensuite, passa aux exemples d'entités multiples avec votre réponse dans le dos de ma tête. Ensuite, il a finalement fait sens. Je passe maintenant la « personne sélectionnée » à mon DreamViewController, parce qu'un objet a toujours une référence à sa ManagedObjectContext Donc DreamViewController je peux mettre ObjectContext comme ceci: NSManagedObjectContext * = contexte self.selectedPerson.managedObjectContext; Je peux évoluer et comprendre cette approche. Merci encore. – RickiG
Vous avez raison, un objet a toujours une référence à son ManagedObjectContext (c'est une propriété). Ma suggestion pour passer le NSManagedObjectContext au contrôleur de vue est juste plus générale et fonctionne dans tous les cas où vous ne passez pas un NSManagedObject au contrôleur mais le contrôleur doit créer un nouveau NSManagedObject pendant son action. –
Il est sorti faux :) Bien sûr, je suis d'accord que le fait de passer le ManagedObjectContext est la façon sûre et pérenne de le faire. Je suppose que c'est un fantôme de mon Java/Flash en pensant que vous essayez d'éviter de passer un "modèle" autour de chaque contrôleur possible, que ce soit un singleton ou non. Juste pour être sûr que j'ai bien compris; mon self.selectedPerson.managedObjectContext est le contexte des personnes (nom de la personne, rêves) et non le modèle entier? Si j'avais réussi le ManagedObjectContext original j'aurais eu accès au modèle entier (d'autres personnes et leurs rêves)? – RickiG