2015-12-27 1 views
6

J'ai un problème avec la récupération d'un objet après avoir ajouté une relation. La première fois que je récupère la catégorie, toujours trouvée, alors quand j'ai ajouté à la relation, les catégories suivantes ne sont pas trouvées.Je n'ai pas trouvé d'objet dans coredata après avoir ajouté à une relation

La relation est un Many-To-Many.

Exemple:

  • Fetch catégorie avec categoryId = 10
  • Objets trouvés catégorie
  • Ajouté à la relation d'objet parent
  • Objet suivant
  • Si plusieurs catégories a la même id, categoryId = 10 , introuvable

    NSManagedObjectContext *private = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
    
        [private setParentContext:self.model.context]; 
        __block NSError *error = nil; 
    
        [private performBlockAndWait:^{ 
    
         GPDeal *deal = [EKManagedObjectMapper objectFromExternalRepresentation:dic withMapping:[GPDeal objectMapping] inManagedObjectContext:private]; 
         for (NSDictionary *dic in responseObject[@"response"]) { 
    
          GPCategory *category; 
    
          //The first time always found 
          if ((category = [GPCategory MR_findFirstByAttribute:@"catId" withValue:dic[@"mainAttribute"] inContext:private])) { 
           NSLog(@"Found"); 
           [category addDealsObject:deal]; 
    
          } else { 
           NSLog(@"Not Found"); 
    
          } 
    
         } 
        }]; 
    
        NSError *PrivateError = nil; 
        if (![private save:&PrivateError]) { 
         NSLog(@"Unresolved error %@, %@", PrivateError, [PrivateError userInfo]); 
         abort(); 
        } 
    
        if (!error) { 
         //Save on main moc 
         [self.model saveWithErrorBlock:^(BOOL success, NSError *error) { 
          if (!success) { 
           NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]); 
          } 
         }]; 
    
        } else { 
         NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]); 
        } 
    

EDIT:

résolu, je suppose que mon problème était que j'ai oublié de sauvegarder le contexte principal à la fin de chaque itération.

 NSManagedObjectContext *backgroundMOC = [self.model backgroundMOC:self.model.context]; 

     [backgroundMOC performBlockAndWait:^{ 

      for (NSDictionary *dic in responseObject[@"response"]) { 

       GPDeal *deal = [EKManagedObjectMapper objectFromExternalRepresentation:dic withMapping:[GPDeal objectMapping] inManagedObjectContext:backgroundMOC]; 

       GPCategory *category; 
       if ((category = [GPCategory MR_findFirstByAttribute:@"catId" withValue:dic[@"mainAttribute"] inContext:backgroundMOC])) { 
        NSLog(@"Found with mainAttribute %@", dic[@"mainAttribute"]); 
        [deal addDealCategoryObject:category]; 
       } 

       if([backgroundMOC hasChanges]) { 
        NSError * error; 
        [backgroundMOC save:&error]; 

        [self.model.context performBlockAndWait:^{ 
         if([self.model.context hasChanges]) { 
          NSError * error; 
          [self.model.context save:&error]; 
         } 
        }]; 
       } 
      } 
     }]; 
+0

Dans quel contexte l'objet 'deal' appartient-il? Il semble que ce soit un contexte différent de 'private'. Vous ne devez pas définir de relations entre des objets dans des contextes différents. Passez le managedObjectID puis récupérez-le dans le contexte 'private' en utilisant' objectWithID'. – pbasdf

+0

J'ai déjà vérifié, mais 'deal' est créé dans le contexte privé – brunobasas

+0

donc votre problème est seulement avec caregoryId = 10? 1ère fois que vous avez 10 dans dic [@ "mainAttribute"] trouvez-vous la catégorie et la 2ème fois non? Le fait que le problème ne provienne pas de MR_findFirstByAttribute m'indique que le problème pourrait être la chaîne contenant l'entier dans dic [@ "mainAttribute"]. pourriez-vous NSLog (@ "ID: -% @ -") afin de vérifier que l'ID n'a pas d'espaces avant ou après? – Mikael

Répondre

1

Vous pouvez manquer de sauvegarder la chaîne MOC. Pour plus de clarté, j'ai remplacé le mot-clé private par le nom de la variable backgroundMOC.

Sur la question ci-dessus, je ne peux supposer que la ligne NSManagedObjectContext *private = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; est techniquement similaire à:

- (NSManagedObjectContext *)backgroundMOC:(NSManagedObjectContext *)mainMOC 
{ 
    NSManagedObjectContext * threadManagedObjectContext = [[NSManagedObjectContext alloc] 
          initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
    [threadManagedObjectContext setParentContext:mainMOC]; 
    [threadManagedObjectContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy]; 
    return threadManagedObjectContext; 
} 

passant self.model.context comme mainMOC, avec un self.model.context et un setMergePolicy.
De même, je dois supposer que self.model saveWithErrorBlock est techniquement identique à:

[mainMOC performBlockAndWait:^{ 
    if([mainMOC hasChanges]) { 
     NSError * error; 
     [mainMOC save:&error]; 
     // handle error 
    } 
}]; 

Si oui, la même chose devrait dire de la backgroundMOC (référence private):

[backgroundMOC performBlockAndWait:^{ 
    if([backgroundMOC hasChanges]) { 
     NSError * error; 
     [backgroundMOC save:&error]; 
     // handle error 
    } 
}]; 

Dans d'autres mots, vous voulez vous assurer que votre opération de sauvegarde backgroundMOC et mainMOC est exécutée à partir de leurs threads respectifs, avec performBlockAndWait.

+0

pouvez-vous regarder ma dernière mise à jour? Appréciez vraiment – brunobasas

+0

Le thread à partir duquel vous exécutez 'performBlockAndWait' pour' self.model.context save' est un sujet de préoccupation. Cela devrait être fait sur le thread principal, ou bien votre 'UI' (disons que vous utilisez' NSFetchedResultsController') peut tomber en panne (voir http://stackoverflow.com/a/6913811/218152). Aussi, si vous avez besoin de '[mainMOC save: & error]' chaque fois que vous [backgroundMOC save: & error] ', vous n'avez pas besoin de' backgroundMOC' en premier lieu: l'idée de 'backgroundMOC' est d'effectuer de longues opérations , ce qui peut ne pas être le cas ici. Plus d'infos: http://stackoverflow.com/search?q=user%3A218152+performBlockAndWait – SwiftArchitect