2013-04-05 11 views
6

Utilizzo i dati principali e ho trovato che l'app talvolta si arrestava in modo anomalo dopo la ripresa dallo sfondo. Ho identificato l'arresto anomalo che si verifica all'interno di un corpo del metodo di blocco quando provo ad accedere a una proprietà in una sottoclasse NSManagedObject.Accesso a un dato principale NSManagedObject dopo la ripresa dallo sfondo arresta l'applicazione

Ho una proprietà che contiene un riferimento a una sottoclasse NSManagedObject.

@property (nonatomic, strong) CalItem * calObject;

Per riprodurre l'incidente ho bisogno di chiamare il bambino viewController (NoteViewController) passando un blocco (NoteTextBlock).

NoteViewController *noteViewController = [[NoteViewController alloc]initWithNote:self.calObject.note NoteTextBlock:^(NSString *noteText) { 
        self.calObject.note = noteText; //crashing here 
       }]; 

Quindi inviare l'app in background e riprenderla. Successivamente in NoteViewController restituirò un messaggio al viewController chiamante.

if (self.noteTextBlock) 
{ 
self.noteTextBlock(trimmedString); 
} 

Quando il blocco ritorna e la linea self.calObject.note = noteText Viene eseguito l'applicazione si blocca.

Quindi a quanto pare non è possibile mettere un blocco in pila, abbastanza e riprendere l'app e quindi continuare con ciò che è stato definito all'interno del blocco? O sto facendo qualcosa di sbagliato qui?

Edit:
*** Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0xb253100 <x-coredata://C2304B7C-7D51-4453-9993-D33B9113A7A5/DTODay/p57>''

Il blocco viene definito in questo modo all'interno del bambino viewController:

@property(nonatomic, copy)NoteTextBlock noteTextBlock; 

Edit2
Questo è ciò che ottengo quando ho creato un punto di interruzione la linea in cui si blocca.
(lldb) po self.calObject
$2 = 0x0b4464d0 <DTODay: 0xb4464d0> (entity: DTODay; id: 0xb489d00 <x-coredata://C2304B7C-7D51-4453-9993-D33B9113A7A5/DTODay/p57> ; data: <fault>)

Sto utilizzando la lib MagicalRecord per gestire tutte le cose Core Data.

- (void)applicationDidBecomeActive:(UIApplication *)application 
{ 
    if ([NSManagedObjectContext MR_defaultContext] == nil 
     || [NSManagedObjectModel MR_defaultManagedObjectModel] == nil 
     || [NSPersistentStoreCoordinator MR_defaultStoreCoordinator] == nil 
     || [NSPersistentStore MR_defaultPersistentStore] == nil 
     ) 
    { 
     //coming back from background, re-init coredata stack 
     [MagicalRecordHelpers setupCoreDataStackWithAutoMigratingSqliteStoreNamed:DBNAME]; 
    } 
+0

Potrebbe fornire al messaggio di incidente? –

+0

Che cos'è il managedObjectContext di calObject prima del crash? È niente? –

+0

Il problema si verifica solo quando l'app si chiude e riprende mentre si utilizza un blocco come callback. In altre situazioni posso tranquillamente riprendere e continuare a usare calObject senza problemi. Potrebbe essere possibile che in qualche modo il blocco o 'sé' all'interno del blocco non venga mantenuto correttamente? – Oysio

risposta

2

non ho familiarità con MagicalRecords, ma ...

Questa eccezione viene sollevata quando si dispone di un (come si può vedere in Edit2) oggetto non-guasto che non è più (o non ha mai avuto) esiste nel negozio.
Ciò può accadere in alcuni casi:

  1. un altro contesto ha cancellato dal negozio
  2. averlo inserito, ottenuto un id permanente per esso e:
    ** rinfrescato lo
    ** salvato (ma solo al contesto genitore), azzerato il genitore, e rinfrescato l'oggetto nel contesto attuale (o importato come colpa al vostro contesto principale), vedi objectWithID:

Potrebbero esserci altri casi che sto dimenticando o ignaro di.

se si potrebbe descrivere la struttura dello stack, e il vostro oggetto di stato/origine potremmo essere in grado di capire meglio il problema

2

Prova anche stato di risparmio su backgound e poi ripristinare lo stato sulla scia nel vostro AppDelegate.m

- (void)applicationDidEnterBackground:(UIApplication *)application { 
     /* 
     Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 
     Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 
     */ 
     [MagicalRecord cleanUp]; 
} 





    - (void) applicationDidBecomeActive:(UIApplication *)application { 
     /* 
     Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 
     */ 
     [MagicalRecord setupCoreDataStackWithStoreNamed:DBNAME]; 
} 
0

Non ho mai usato Magico, ma sembra a me che si sta ricostruendo una esistente Core Lo stack di dati quando l'applicazione diventa di nuovo attiva. Immagino che quello che vuoi veramente sia impostare i Core Data in applicationDidFinishLaunching:(UIApplication *) anziché applicationDidBecomeActive:(UIApplication *).

Il primo imposterà lo stack solo all'avvio dell'app, mentre il secondo reimposterà lo stack ogni volta che l'app si "sveglierà".

Il problema è che hai quindi creato un nuovo stack di Core Data, pur avendo oggetti che fanno riferimento al vecchio stack di Core Data.

In generale, quando si avvia l'app, si desidera creare lo stack.Puoi provare a rimuovere in modo pulito lo stack quando l'app termina. Tuttavia, quando va semplicemente in background, dovresti semplicemente salvare i dati, e quindi non devi fare nulla quando l'app viene semplicemente riattivata.

+0

Questo non causerà l'eccezione, solo gli oggetti orfani se non ha un contesto mantenuto (tutte le proprietà saranno annullate) –

Problemi correlati