Question

J'utilise RestKit à des objets d'appui de mon service RoR et en utilisant CoreData persister quelques-uns des objets (plus d'objets de table de consultation de type statique). TasteTag est l'un de ces objets persistaient:

#ifdef RESTKIT_GENERATE_SEED_DB
    NSString *seedDatabaseName = nil;
    NSString *databaseName = RKDefaultSeedDatabaseFileName;
#else
    NSString *seedDatabaseName = RKDefaultSeedDatabaseFileName;
    NSString *databaseName = @"Model.sqlite";
#endif

RKObjectManager* manager = [RKObjectManager objectManagerWithBaseURL:kServerURL];  
manager.objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:databaseName usingSeedDatabaseName:seedDatabaseName managedObjectModel:nil delegate:self];

.. lots of fun object mapping ..

 RKManagedObjectMapping* tasteTagMapping = [RKManagedObjectMapping mappingForClass:[TasteTag class]];
[tasteTagMapping mapKeyPath:@"id" toAttribute:@"tasteTagID"];
[tasteTagMapping mapKeyPath:@"name" toAttribute:@"name"];
tasteTagMapping.primaryKeyAttribute = @"tasteTagID";
[[RKObjectManager sharedManager].mappingProvider setMapping:tasteTagMapping forKeyPath:@"taste_tags"]; 
[[RKObjectManager sharedManager].mappingProvider addObjectMapping:tasteTagMapping];

.. some more mapping ..

J'ai les données qui reviennent du serveur RoR et il devient mappées à des objets comme prévu. L'entité de données de base semble aussi très bien cartographié après RestKit revient la demande:

"<TasteTag: 0x6e87170> (entity: TasteTag; id: 0x6e85d60 <x-coredata://03E4A20A-21F2-4A2D-92B4-C4424893D559/TasteTag/p5> ; data: <fault>)"

La question est quand je tente d'accéder aux propriétés sur les objets de la faute ne peut pas sembler être le feu. Au début, je vient d'appeler les propriétés, ce qui revenait toujours comme nul (même si cela ne devrait tirer la faute):

for (TasteTag *tag in self.vintage.tasteTags) {
    [tagNames addObject:tag.name]; //get error of trying to add nil to array   
}

Après avoir examiné le déclenchement manuel des défauts ( http://www.mlsite.net/blog/?p=518 ) J'ai essayé d'appeler [tag willAccessValueForKey:nil] qui se traduit par:

Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0x6e7b060 <x-coredata://03E4A20A-21F2-4A2D-92B4-C4424893D559/TasteTag/p5>''

Recherche l'entité dans le .sqlite en fonction de la clé (TasteTag / p5) ne montrer mis en correspondance avec celui que je me attends.

D'autres messages relatifs à RestKit la désactivation du cache recommandent d'objet (que je ne suis pas en utilisant) car cela est généralement causée par une entité en cours de suppression. Mais à ce stade, je suis en train de lire, ne pas supprimer, et je ne cache en place.

Si je viens [TasteTag allObjects] appel que je suis en mesure d'obtenir tous les objets bien en arrière et ils chargent sans problème. Il est juste dans le cas où ils sont blâmés il semble.

Était-ce utile?

La solution 2

Documenter mon fix (lire: bidouille). Par la suggestion de Ryan

L'erreur semble être dans la façon dont RestKit suppose que vous allez utiliser les objets retournés de leur méthode objectLoader:didLoadObjects:. Ils semblent assumer tout sera de base de données sauvegardées (et suivre le flux similaire à ce que Ryan a parlé - laisser synchroniser à base de données, puis re-requête) ou que vous allez utiliser tous les objets non de base de données sauvegardées et juste garder ces résultats autour.

Dans mon cas, j'ai eu un mélange - un tableau de racine d'objets non adossées à des données de base dont chacun contient alors un tableau de base de données sauvegardées entités. Les objets de haut niveau sont ceux que je ne me dérange pas d'interroger le serveur et avoir aucune raison de persister localement au-delà de la vue qu'ils sont présentés dans. Il semble une fois objectLoader:didLoadObjects: est terminé, le contexte de l'objet géré soutenir les entités de base de données au sein du objects pARAM est mis au rebut (en supposant que vous serez re-interroger pour eux), ce qui provoque des appels futurs aux entités aboutir à être traitées comme des défauts, même si vous ne pouvez pas déclencher le défaut et charger les données (résultats en NSObjectInaccessibleException).

je me suis autour d'elle avec une bidouille horrible - au sein objectLoader:didLoadObjects: je un accès de l'objet géré par l'entité de données de base du contexte et de le copier sur une propriété dans la vue (self.context = [tag managedObjectContext];). Cela évite le contexte étant libéré après objectLoader:didLoadObjects: est terminée, me permettant d'accéder à des entités sans problème plus tard dans la vue.

Une autre solution serait de re-requête manuellement pour chaque entité en utilisant un nouveau contexte et copier ce retour aux objets de retour stockés. On pourrait le faire quand on va les afficher, ou peut-être un peu de post-traitement dans objectLoader:didLoadObjects:, en utilisant un nouveau contexte. L'ID d'entité est toujours autour de l'objet faillé si on pouvait l'utiliser pour re-requête sans problème, même après le contexte de disparait RestKit d'origine. Mais il semble stupide d'avoir à re-requête pour chaque entité dans le graphe d'objet comme ça.

Autres conseils

J'ai trouvé une solution qui a fonctionné pour moi (je ne suis pas sûr de la façon dont il sera applicable à votre situation, mais je l'ajouter comme une réponse car il a résolu ce (ou similaire) problème pour moi):

A deux jours de retour, j'ai couru l'exemple de RKTwitterCoreData et a remarqué qu'il a parfaitement fonctionné alors que le mien, avec le code très simple à ce point et faire à peu près la même chose, ne l'a pas. Je suis un beaucoup de défauts non tenues. J'ai donc décidé de modifier tout mon code GÉRER RestKit pour refléter la façon dont l'exemple RKTwitterCoreData fait.

Je vais diviser cela en morceaux pour essayer de vous aider à suivre ma ligne de pensée à l'époque (puisque je ne pense pas que nos problèmes sont identiques).

Ma mise en œuvre originale Assomption

Depuis RestKit peut sauvegarder des objets à base de données, je suppose que ces objets gérés peuvent être utilisés de manière interchangeable. Par exemple, je pourrais utiliser les objets à partir des données de base de la même manière exacte que ceux récupérés à partir d'un service Web à distance. Je ne pouvais même les fusionner ensemble pour obtenir toutes les données.

I Was Wrong

J'ai remarqué le code que RKTwitterCoreData a fait pas Flux de cette façon dans le moins. Un morceau digne de mon code correspondait avec eux, mais la plus grande différence est qu'ils ne traitent pas ces objets comme interchangeables. En fait, ils jamais utilisé les objets qu'ils ont obtenu de magasins de données à distance. Au lieu de cela, ils laissent juste que « passer à travers les mailles du filet ». Je ne peux que supposer que des moyens ils sont ajoutés à la banque de données de base de données, car il fonctionne pour eux et, maintenant, pour moi.

Détails

Mon application a travaillé après avoir modifié mon code pour utiliser ce flux. Je ne peux donc supposer que les défauts irréalisables que nous voyons sont liés à l'utilisation des données de base des objets sauvegardés que nous revenions du service Web . Si au contraire vous ignorez les et faites chercher, vous aurez tout retour (y compris la plus récente demande) et vous ne devriez pas avoir des défauts impossibles à satisfaire.

Pour élaborer, si vous regardez RKTwitterViewController vous remarquerez que les lignes 45-61 de chargement poignée d'objets:

- (void)loadObjectsFromDataStore {
    [_statuses release];
    NSFetchRequest* request = [RKTStatus fetchRequest];
    NSSortDescriptor* descriptor = [NSSortDescriptor sortDescriptorWithKey:@"createdAt" ascending:NO];
    [request setSortDescriptors:[NSArray arrayWithObject:descriptor]];
    _statuses = [[RKTStatus objectsWithFetchRequest:request] retain];
}

- (void)loadData {
    // Load the object model via RestKit    
    RKObjectManager* objectManager = [RKObjectManager sharedManager];
    [objectManager loadObjectsAtResourcePath:@"/status/user_timeline/RestKit" delegate:self block:^(RKObjectLoader* loader) {
        // Twitter returns statuses as a naked array in JSON, so we instruct the loader
        // to user the appropriate object mapping
        loader.objectMapping = [objectManager.mappingProvider objectMappingForClass:[RKTStatus class]];
    }];
}

Tout semble normal (au moins par rapport à ce que je faisais ce chargement au départ). Mais jetez un oeil à la méthode de délégué objectLoader:didLoadObjects::

- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {
    [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:@"LastUpdatedAt"];
    [[NSUserDefaults standardUserDefaults] synchronize];
    NSLog(@"Loaded statuses: %@", objects);
    [self loadObjectsFromDataStore];
    [_tableView reloadData];
}

L'échantillon ne touche même pas le paramètre objects! (Mis à part le NSLog bien sûr ...)

Conclusion / tl; dr

Ne pas utiliser les objets gérés vous revenez dans objectLoader:didLoadObjects: comme si elles sont entièrement soutenues par Core Data. Au lieu de cela, les ignorer et récupérer à nouveau de base de données. Tous les objets, y compris ceux de la dernière demande sont là. Dans le cas contraire, vous obtiendrez des défauts irréalisables (au moins je l'ai fait).

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