2015-10-16 5 views
8

Manchmal (selten aber auftritt) habe ich Fehler Object has been deleted or invalidated., wenn ich versuche, mein Modellobjekt mit einer Eigenschaft oder in AFnetworking Block zu ändern. Kann mir jemand helfen zu finden, was ich falsch mache?Fehler: Objekt wurde gelöscht oder ungültig gemacht. (Realm)


Fehler - Fall 1:

Code:

- (void)myFunction { 
    Model *model = [Model objectForPrimaryKey:1]; 

    if (model) { 
     [self updateModel:model]; 
    } 
} 

- (void)updateModel:(Model *)model { 

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
    [manager PUT:@"http://www.example.com" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) { 

     [[RLMRealm defaultRealm] beginWriteTransaction]; 
     model.updated = YES; // Crash: Object has been deleted or invalidated. 
     [[RLMRealm defaultRealm] commitWriteTransaction]; 

    } failure:nil]; 
} 

Fehler - Fall 2:

Eigentum:

@property (strong, nonatomic) Model *model; 

Code:

- (void)myFunction { 
    Model *model = [Model objectForPrimaryKey:1]; 

    if (model) { 
     self.model = model; 

     UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"" message:@"Would you like to edit the model?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Ok", nil]; 
     [alert show]; 
    } 
} 

UIAlertView Delegierten:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { 
    if (buttonIndex == 1) { 
     [[RLMRealm defaultRealm] beginWriteTransaction]; 
     self.model.updated = YES; // Crash: Object has been deleted or invalidated. 
     [[RLMRealm defaultRealm] commitWriteTransaction]; 
    } 
} 

Dank.

Antwort

7

Wie in Beispiel 1 wird die Netzwerkanforderung asynchron auf einer anderen Operationswarteschlange ausgeführt und ruft zurück zum Hauptthread. Es ist sehr wahrscheinlich, dass Sie einen Code haben, der in der Zwischenzeit durch eine Benutzeraktion ausgelöst werden kann Objekt gleichzeitig. Die Modellobjekt-Referenz, die Sie halten, wird automatisch aktualisiert und spiegelt das Löschen wider. Da ein gelöschtes Objekt nicht geändert werden kann, kommt es zu dem Fehler.

Auch Beispiel 2 beinhaltet Nebenläufigkeit. Ihr Code ruft zuerst das Modellobjekt ab und zeigt dann die Alarmansicht an. Während der UIAlertView angezeigt wird, ist der Haupt-Thread nicht blockiert. Theoretisch könnte gleichzeitig ein Netzwerkvorgang, der zuvor in die Warteschlange gestellt wurde, enden, der Abschlussblock könnte ausgelöst werden, ein Löschen des Modellobjekts tritt auf. Der Benutzer bestätigt die Änderungen. Ihre Implementierung des Delegaten wird aufgerufen, erwartet jedoch, dass das zuvor abgerufene Objekt noch vorhanden ist.

Eine Möglichkeit zur Vermeidung von Abstürzen besteht darin, nur einen Primärschlüssel anstelle eines vollständigen Modellobjektverweises zu speichern, der die letzten Änderungen aktualisiert und widerspiegelt. Der Primärschlüssel bleibt konstant und sollte immer in der Lage sein, Ihr Objekt zu identifizieren. Sie können den Primärschlüssel später verwenden, um das Objekt direkt in Ihrer Schreibtransaktion abzurufen.

Beachten Sie, dass es in jedem Fall an Ihnen liegt zu definieren, wie sich Ihre App verhält, wenn Ihre Daten gleichzeitig geändert wurden. Sie können versuchen, das Objekt neu zu erstellen, indem Sie mehr Daten in der Kopie belassen, das Ereignis ignorieren und das Löschen gewinnen lassen oder sicherstellen, dass keine widersprüchlichen Änderungen auftreten, indem Sie die Benutzeroberfläche angemessen einschränken. Sie müssen eine Konfliktlösungsstrategie entwickeln.

+0

Statt das Modell zu senden, habe ich den Modell-Primärschlüssel gesendet, und jedes Mal, wenn es notwendig ist, versuche ich, es vorher zu finden. Crash ist weg und es funktioniert richtig, danke! –