2013-04-05 7 views
6

I Kerndaten sind mit und habe die App manchmal Absturz nach der Rückkehr aus dem Hintergrund gefunden. Ich habe den Absturz innerhalb eines Blockmethoden-Bodys erkannt, als ich auf eine Eigenschaft in einer Unterklasse zugreifen wollte.eine Kerndatum NSManagedObject Zugriff, nachdem sie von der Wiederaufnahme Hintergrund stürzt die App

Ich habe eine Eigenschaft, die einen Verweis auf eine NSManagedObject Unterklasse hält.

@Eigenschaft (nichtatomisch, stark) CalItem * calObject;

den Absturz reproduzieren ich das Kind Viewcontroller zuerst anrufen müssen (NoteViewController), die einen Block (NoteTextBlock).

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

Dann senden Sie die App zum Hintergrund und fortsetzen Sie es. Danach im NoteViewController ich werde eine Nachricht an den aufrufenden ViewController zurückgeben.

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

Wenn der Block zurückkehrt und die Linie self.calObject.note = noteText die Abstürze App ausgeführt wird.

So anscheinend können Sie keinen Block auf den Stapel gelegt, ganz und die App wieder aufnehmen und dann mit fortführen, was im Inneren des Blocks definiert wurde? Oder mache ich hier gerade etwas falsch?

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>''

Der Block wie diese im Inneren des Kindes definiert ist Viewcontroller:

@property(nonatomic, copy)NoteTextBlock noteTextBlock; 

EDIT2
Dies ist, was ich bekomme, wenn ich einen Haltepunkt setzen auf die Linie, wo es abstürzt.
(lldb) po self.calObject
$2 = 0x0b4464d0 <DTODay: 0xb4464d0> (entity: DTODay; id: 0xb489d00 <x-coredata://C2304B7C-7D51-4453-9993-D33B9113A7A5/DTODay/p57> ; data: <fault>)

Ich bin mit dem MagicalRecord lib die Core Data alle Sachen zu verwalten.

- (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

Könnten Sie die Crash-Meldung zur Verfügung stellen? –

+0

Was ist der managedObjectContext des calObject vor dem Absturz? Ist es Null? –

+0

Das Problem tritt nur auf, wenn die App während der Verwendung eines Blocks als Rückruf beendet wird. In anderen Situationen kann ich calObject problemlos und ohne Probleme weiter verwenden. Könnte es möglich sein, dass der Block oder das "Selbst" innerhalb des Blocks irgendwie nicht richtig beibehalten wird? – Oysio

Antwort

2

Ich bin nicht vertraut mit MagicalRecords, aber ...

Diese Ausnahme wird ausgelöst, wenn Sie ein un-bemängelt haben (wie in EDIT2 zu sehen) Objekt, das nicht mehr (oder noch nie) existiert im Laden.
Dies könnte in einigen Fällen geschehen:

  1. Ein weiterer Kontext es aus dem Laden
  2. Sie es eingefügt haben gelöscht, denn es ist eine permanente ID erhalten und:
    ** es aktualisiert
    ** sie gespeichert (aber nur in dem übergeordneten Kontext), reseted die Eltern, und aktualisierte das Objekt im aktuellen Kontext (oder es als Fehler zu Ihrem Haupt Kontext importiert), siehe objectWithID:

Es könnte andere Fälle geben, die ich vergesse oder nicht weiß.

, wenn Sie Ihre Stapelstruktur beschreiben könnten, und Ihr Objektzustand/Herkunft könnten wir in der Lage sein, das Problem besser zu verstehen

2

auch versuchen Zustand auf backgound speichern und dann Zustand Wiederherstellung auf Wake in Ihrem AppDelegate.m up

- (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

Ich habe noch nie magischen Rekord verwendet, aber es scheint mir, dass Sie ein neu erstellen bestehenden Core Data Stack, wenn die Anwendung wieder aktiv wird. Ich stelle mir vor, was Sie wirklich tun möchten, ist die Core-Daten in applicationDidFinishLaunching:(UIApplication *) statt applicationDidBecomeActive:(UIApplication *) einrichten.

Erstere wird nur Setup der Stapel, wenn die App startet, während die letztere wird wieder Setup den Stack jedes Mal die App „aufwacht.“

Das Problem ist, dass man dann einen neuen Core Data-Stack erstellt haben, während Objekte mit, die den alten Core Data Stapel verweisen.

Im Allgemeinen, wenn die Anwendung gestartet wird, möchten Sie Ihren Stapel erstellen.Sie können versuchen, den Stapel sauber zu entfernen, wenn die App beendet wird. Wenn es jedoch nur in den Hintergrund geht, sollten Sie einfach die Daten speichern, und dann müssen Sie wirklich nichts tun, wenn die App einfach wieder aktiviert wird.

+0

Dies wird nicht die Ausnahme verursachen, nur die Objekte verwaisen, wenn er keinen beibehaltenen Kontext hat (alle Eigenschaften werden aufgehoben) –