2015-12-27 36 views
6

Mam problem z pobieraniem obiektu po dodaniu go w relacji. Pierwszy raz, kiedy pobierałem kategorię, zawsze znajdowałem, a następnie dodałem do relacji następujące kategorie nie znaleziono.Nie znaleziono obiektu w coredatach po dodaniu do relacji

Związek to Many-To-Many.

Przykład:

  • Fetch kategoria z categoryId = 10
  • kategoria obiektu
  • Dodano do relacji nadrzędny obiekt
  • Następny obiekt
  • Jeżeli kilka kategorii ma taką samą id, categoryId = 10 , nie znaleziono

    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:

rozwiązany, myślę, że moim problemem było to, że zapomniałem zapisać główny kontekst, w końcu każdej iteracji.

 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

Do jakiego kontekstu należy obiekt 'deal'? Wygląda na to, że musi to być inny kontekst niż "prywatny". Nie powinieneś ustawiać relacji między obiektami w różnych kontekstach. Przekaż obiekt managedObjectID, a następnie pobierz go w kontekście "private", używając parametru "objectWithID". – pbasdf

+0

Sprawdziłem już, ale "deal" jest tworzony wewnątrz prywatnego kontekstu – brunobasas

+0

, więc twój problem jest tylko z caregoryId = 10? 1. raz masz 10 w dic [@ "mainAttribute"] znajduje kategorię, a po raz drugi nie? Fakt, że problem może nie pochodzić z MR_findFirstByAttribute mówi mi, że problem może być ciągiem zawierającym liczbę całkowitą w dic [@ "mainAttribute"]. czy mógłbyś NSLog (@ "ID: -% @ -") w celu sprawdzenia, czy ID nie ma spacji przed lub po? – Mikael

Odpowiedz

1

Być może brakuje Ci zapisania łańcucha MOC. Dla jasności zastąpiłem słowo kluczowe private zmienną o nazwie backgroundMOC.

Na powyższe pytanie, mogę tylko przypuszczać, że linia NSManagedObjectContext *private = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; jest technicznie podobny do:

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

przechodząc self.model.context jak mainMOC, z self.model.context i setMergePolicy.
Podobnie, muszę założyć, że self.model saveWithErrorBlock jest technicznie identyczna:

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

Jeśli tak, to samo należy powiedzieć o backgroundMOC (odniesienia private):

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

w innych słowa, chcesz upewnić się, że twoja operacja składowania backgroundMOC i jest wykonywana z ich odpowiednich wątków, z performBlockAndWait.

+0

Czy możesz obejrzeć moją ostatnią aktualizację postu? naprawdę doceniam: – brunobasas

+0

Niepokojący jest wątek, z którego wykonujesz 'performBlockAndWait' dla' self.model.context save'. To powinno być zrobione w głównym wątku, inaczej twój "UI" (powiedzmy, że używasz 'NSFetchedResultsController') może ulec awarii (patrz http://stackoverflow.com/a/6913811/218152). Ponadto, jeśli potrzebujesz '[mainMOC save: & error]' za każdym razem, gdy '[backgroundMOC save: & error]', możesz nie potrzebować 'backgroundMOC' na pierwszym miejscu: ideą' backgroundMOC' jest wykonywanie długich operacji , co może nie mieć miejsca w tym przypadku. Więcej informacji: http://stackoverflow.com/search?q=user%3A218152+performBlockAndWait – SwiftArchitect