2013-02-14 9 views
5

Mam następujący kod:MagicalRecords trwa w wątku tła z pobierania obrazu?

dispatch_async(dispatch_get_main_queue(), ^{ 
    NSManagedObjectContext *localContext = [NSManagedObjectContext contextForCurrentThread]; 

    Item *newItem = [Item createInContext:localContext]; 
    newItem.title = NULL_TO_NIL([itemJson valueForKey:@"title"]); 
    newItem.image_url = NULL_TO_NIL([itemJson valueForKey:@"image_url"]); 
    newItem.order_id = @([[self largestOrderId] intValue] + 1); 

    NSURL *url = [NSURL URLWithString:newItem.image_url]; 
    NSData *data = [[NSData alloc] initWithContentsOfURL: url]; 
    if (data == nil) { 
     NSLog(@"Image data is nil from %@", url); 
    } else { 
     NSLog(@"Image fetched in saveItemFromJson for cid:%@ order_id:%@", newItem.cid, newItem.order_id); 
     newItem.image = [UIImage imageWithData:data]; 
    } 

    if (![localContext hasChanges]) { 
     NSLog(@"No local change detected. Quitting"); 
     return; 
    } 

    [localContext saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) { 
     if (!success) 
      NSLog(@"Error: %@", [error localizedDescription]); 
     else 
      NSLog(@"Item persisted for cid:%@ order_id:%@", newItem.cid, newItem.order_id); 
    }]; 
}); 

I wydają się być coraz wiele z następujących czynności:

2013-02-13 18:55:47.404 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8386a90) → Saving <NSManagedObjectContext (0x8386a90): *** DEFAULT ***> on *** MAIN THREAD *** 
2013-02-13 18:55:47.404 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8386a90) → Save Parents? 1 
2013-02-13 18:55:47.404 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8386a90) → Save Synchronously? 0 
2013-02-13 18:55:47.497 Giordano.iPhone[13956:c07] Image fetched in saveItemFromJson for cid:7218 order_id:10 
2013-02-13 18:55:47.497 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8386a90) → Saving <NSManagedObjectContext (0x8386a90): *** DEFAULT ***> on *** MAIN THREAD *** 
2013-02-13 18:55:47.498 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8386a90) → Save Parents? 1 
2013-02-13 18:55:47.498 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8386a90) → Save Synchronously? 0 
2013-02-13 18:55:47.499 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x8386a90) Context DEFAULT is about to save. Obtaining permanent IDs for new 10 inserted objects 
2013-02-13 18:55:47.501 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8385aa0) → Saving <NSManagedObjectContext (0x8385aa0): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD *** 
2013-02-13 18:55:47.502 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8385aa0) → Save Parents? 0 
2013-02-13 18:55:47.502 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8385aa0) → Save Synchronously? 1 
2013-02-13 18:55:47.502 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x8385aa0) Context BACKGROUND SAVING (ROOT) is about to save. Obtaining permanent IDs for new 10 inserted objects 
2013-02-13 18:55:47.505 Giordano.iPhone[13956:c07] __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke21(0x8385aa0) → Finished saving: <NSManagedObjectContext (0x8385aa0): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD *** 
2013-02-13 18:55:47.505 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8385aa0) NO CHANGES IN ** BACKGROUND SAVING (ROOT) ** CONTEXT - NOT SAVING 

z następujących komunikatów o błędach:

2013-02-13 18:55:47.511 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8385aa0) NO CHANGES IN ** BACKGROUND SAVING (ROOT) ** CONTEXT - NOT SAVING 
2013-02-13 18:55:47.512 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8385aa0) NO CHANGES IN ** BACKGROUND SAVING (ROOT) ** CONTEXT - NOT SAVING 
2013-02-13 18:55:47.512 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8385aa0) NO CHANGES IN ** BACKGROUND SAVING (ROOT) ** CONTEXT - NOT SAVING 
2013-02-13 18:55:47.512 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8385aa0) NO CHANGES IN ** BACKGROUND SAVING (ROOT) ** CONTEXT - NOT SAVING 
2013-02-13 18:55:47.513 Giordano.iPhone[13956:c07] -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8385aa0) NO CHANGES IN ** BACKGROUND SAVING (ROOT) ** CONTEXT - NOT SAVING 


2013-02-13 18:55:47.515 Giordano.iPhone[13956:c07] Error: (null) 
2013-02-13 18:55:47.515 Giordano.iPhone[13956:c07] Error: (null) 
2013-02-13 18:55:47.515 Giordano.iPhone[13956:c07] Error: (null) 

ja unikając używać saveInBackgroundWithBlock, ponieważ jest on przestarzały (dokumenty muszą zostać zaktualizowane?)

Jakieś pomysły z tym, co jest nie tak z moim kodem?

UPDATE

Mój zespół zdecydował, że MagicalRecord jest zbyt buggy teraz. Całkowicie przenieśliśmy nasz kod z MR z powrotem do CoreData. Dziękuję za uwagę.

+0

Jaki jest Twój główny cel? –

Odpowiedz

0

Czy próbowałeś już MR_saveOnlySelfWithCompletion:?

2

Miałem ten sam problem! Zostało to naprawione tylko wtedy, gdy zrobiłem zapisywanie kontekstu ręcznie przeze mnie bez MR.

tu jest moje rozwiązanie:

NSManagedObject + MyCategory.h

+ (void)saveDataInBackgroundWithBlock:(void(^)(NSManagedObjectContext *localContext))saveBlock 
          completion:(void(^)(void))completion; 

+ (NSManagedObjectContext *)newMergableBackgroundThreadContext; 

- (void)saveWithCompletion:(void(^)(void))completion; 

.m

+ (NSManagedObjectContext *)newMergableBackgroundThreadContext { 
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
    context.parentContext = [self mainThreadContext]; 
    [context.userInfo setObject:[NSNumber numberWithInteger:VKCoreDataManagedObjectContextIDTempBackground] 
         forKey:@"contextID"]; 
    [context.userInfo setObject:kVKCoreDataManagedObjectContextBackgroundTemp 
         forKey:@"contextDebugName"]; 
    VKDLog(@"* New mergable backround context created! *"); 
    return context; 
} 

+ (void)saveDataInBackgroundWithBlock:(void (^)(NSManagedObjectContext *))saveBlock completion:(void (^)(void))completion { 
    NSManagedObjectContext *tempContext = [self newMergableBackgroundThreadContext]; 
    [tempContext performBlock:^{ 

     if (saveBlock) { 
      saveBlock(tempContext); 
     } 

     if ([tempContext hasChanges]) { 
      [tempContext saveWithCompletion:completion]; 
     } else { 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       if (completion) { 
        completion(); 
       } 
      }); 
     } 
    }]; 
} 

- (void)saveWithCompletion:(void(^)(void))completion { 
    [self performBlock:^{ 
     NSError *error = nil; 
     if ([self save:&error]) { 
      NSNumber *contextID = [self.userInfo objectForKey:@"contextID"]; 
      if (contextID.integerValue == VKCoreDataManagedObjectContextIDMainThread) { 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        if (completion) { 
         completion(); 
        } 
       }); 
      } 
      [[self class] logContextSaved:self]; 
      if (self.parentContext) { 
       [self.parentContext saveWithCompletion:completion]; 
      } 
     } else { 
      [VKCoreData handleError:error]; 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       if (completion) { 
        completion(); 
       } 
      }); 
     } 
    }]; 
} 

i tu jest za pomocą próbki:

[NSManagedObjectContext saveDataInBackgroundWithBlock:^(NSManagedObjectContext *localContext){ 
// do your stuff with local context 
} completion:^{ 
// handle completion, update UI or something 
}]; 
+0

dzięki. Zrobiliśmy coś bardzo podobnego również bez MR. – disappearedng

2

miałem podobny problemy przy użyciu M R kilka tygodni temu. W końcu postanowiłem go wyrzucić i zrobić wszystko samemu. Naprawdę nie jest to rozwiązanie twojego problemu, ale rozumowanie za mną upuszczając to jest dźwięk. Prawdopodobnie musisz iść i spojrzeć na rzeczywiste źródło MR. Duża część dokumentacji jest niepoprawna, a sporej części biblioteki można się nauczyć tylko czytając źródło. Najprawdopodobniej problem z próbowaniem przetwarzania w tle za pomocą MR.

Jeśli twój kod jest dla iOS6 +, powinieneś po prostu użyć ustawienia kontekstowego Master-Main-Child. Używanie dispatch_async jest prawdopodobnie również problemem. Pozwalając Core Data zarządzać twoimi wątkami za pomocą metody [NSManagedContext performBlock:] jest prawdopodobnie bezpieczniejszy cały świat.

Jeśli używasz systemu iOS5 lub niższego, kod kontekstu Child i performBlock: nie działa. Najprostszym rozwiązaniem jest utrzymanie Core Data z wątków. Wyciągnij wszelkie potrzebne informacje z danych podstawowych przed wprowadzeniem nowego wątku/bloku. Przekaż te dane do swojego bloku i wykonaj niezbędne przetwarzanie. Następnie wróć do głównego wątku w jakimś słowniku/obiekcie i wykonaj tam zapisywanie danych podstawowych.

Też zauważyłem, że natknąłem się na tę kwestię, ponieważ pobierałem obrazy i zapisywałem je w Core Data, możesz też spojrzeć na te pytania, które zadałem/rozwiązałem w ciągu ostatnich kilku tygodni.Możecie zapisać wyciągając jakieś włosy później:

Can I access the files used for external binary storage in Core Data?

co ostatecznie doprowadzi mnie używając mojego własny mechanizm przechowywania zamiast danych Core dla plików, a co ostatecznie doprowadzi mnie do tego problemu/rozwiązania:

Files are no longer readable after updating application to newest version

+0

Dzięki. Sam też upuściłem MR – disappearedng