2013-02-14 2 views
5

Ho il seguente codice:MagicalRecords persistente nel thread in background con recupero immagini?

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); 
    }]; 
}); 

mi sembra di essere sempre un sacco di quanto segue:

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 

Con i seguenti messaggi di errore:

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) 

sto evitando di utilizzare saveInBackgroundWithBlock perché è deprecato (i documenti devono essere aggiornati?)

Qualche idea con cosa c'è di sbagliato nel mio codice?

UPDATE

La mia squadra ha deciso che MagicalRecord è troppo bacato per ora. Abbiamo completamente migrato il nostro codice da MR a CoreData. Grazie per l'attenzione.

+0

Qual è il tuo obiettivo principale? –

risposta

0

Hai provato MR_saveOnlySelfWithCompletion:?

2

Ho avuto lo stesso problema! È stato corretto solo quando ho salvato manualmente il contesto manualmente senza MR.

Ecco la mia soluzione:

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(); 
       } 
      }); 
     } 
    }]; 
} 

e qui sta usando campione:

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

grazie. Abbiamo fatto qualcosa di molto simile anche senza MR. – disappearedng

2

ho avuto simili problemi usando M R alcune settimane fa. Alla fine ho deciso di abbandonarlo e fare tutto da solo. Non è davvero una soluzione al tuo problema, ma il ragionamento dietro di me che lo fa cadere è sano. Probabilmente hai bisogno di andare a dare un'occhiata alla fonte reale di MR. Una buona parte della documentazione non è corretta e una buona parte della biblioteca può essere appresa solo leggendo la fonte. Molto probabilmente c'è un problema con il tentativo di eseguire l'elaborazione in background con MR.

Se il codice è per iOS6 +, è sufficiente utilizzare l'impostazione del contesto Master-Main-Child. Anche l'uso di dispatch_async è probabilmente un problema. Lasciare che i dati di base gestiscano la filettatura utilizzando il metodo [NS: PerformBlock:] è probabilmente un mondo più sicuro.

Se si utilizza iOS5 o inferiore, il contesto figlio e performBlock: il codice non funziona. La soluzione più semplice è mantenere i Core Data fuori dai tuoi thread. Tirare tutte le informazioni necessarie da Core Data prima di inserire il nuovo thread/blocco. Trasferisci i dati nel tuo blocco ed esegui tutte le elaborazioni necessarie. Quindi torna al thread principale in un dizionario/oggetto di qualche tipo ed esegui il salvataggio dei tuoi dati core lì.

Anche una nota a margine, ho riscontrato questo problema a causa del download di immagini e del loro salvataggio in Core Data, potreste voler dare un'occhiata a queste domande che ho chiesto/risolto nelle ultime settimane relative a questo.Potrebbe risparmiare tirando un po 'i capelli in seguito:

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

che alla fine mi ha portato usando il mio proprio meccanismo, invece di Core Data per i file di archiviazione, e che alla fine mi ha portato a questo problema/soluzione:

Files are no longer readable after updating application to newest version

+0

Grazie. Anch'io ho lasciato cadere MR – disappearedng