2 Stimmen

PFUser wirft eine NSInternalInconsistencyException, wenn objectForKey nach fetchAllIfNeeded aufgerufen wird

Ich habe zwei zusätzliche Spalten auf meinem PFUser "Vorname" und "Nachname". Sie werden ordnungsgemäß gespeichert; Ich kann die Daten im Datenbrowser sehen.

Ich habe ein weiteres PFObject "Klasse", das eine Eigenschaft mit einem NSArray von PFUsers hat. Ich verwende die Klassenmethode +fetchAllIfNeededInBackground:block: auf PFObject, um das Array von PFUsers abzurufen. Im Callback-Block rufe ich objectForKey: für jeden der PFUsers im Array auf, aber ich greife über das zugehörige PFObject darauf zu.

// invited ist das NSArray der PFUsers
self.whoCell.mainLabel.text = [[self.plan.invited objectAtIndex:0] 
                                                  objectForKey:@"firstName"];

Der Debugger gibt dies bei einem Haltepunkt direkt vor dem objectForKey-Aufruf aus:

(lldb) po self.plan.invited
(NSArray *) $4 = 0x06e62a60 <__NSArrayM 0x6e62a60>(
 {
    firstName = Fake;
    lastName = Account;
    username = yyajnbafv53qw4yhjm9sfoiis;
}
)

Bearbeiten: Implementierung von self.plan.invited hinzufügen, weil das oben irreführend ist.

- (NSArray*)invited
{
  // self.dataSource ist ein PFObject*
  return [self.dataSource objectForKey:INVITED_PROP];
}

Aber wenn der obige Aufruf von objectForKey: gemacht wird, wird diese Ausnahme ausgelöst:

'NSInternalInconsistencyException', reason: 'Der Schlüssel "firstName" enthält keine Daten. Rufen Sie fetchIfNeeded auf, bevor Sie seinen Wert abrufen.'

Bearbeiten: Der Zugriff auf das Array der fetchedObjects, das an den Block-Callback für +fetchAllIfNeededInBackground übergeben wird, löst keine Ausnahme aus, aber der Zugriff auf das tatsächliche Array, das ursprünglich an +fetchAllIfNeededInBackground übergeben wurde, wirft eine Ausnahme.

Das Aufrufen von fetchIfNeeded vor dem Aufruf löst das Problem, aber warum? Die Daten sind bereits vorhanden. Verstehe ich +fetchAllIfNeededInBackground falsch, dass es das PFObject, das die Sammlung von PFUsers besitzt, NICHT aktualisiert?

6voto

squinlan Punkte 1795

Ich habe herausgefunden, was passiert ist. Lassen Sie mich das mit Code erklären:

PFQuery *query = [PFQuery queryWithClassName:@"TestClass"];
PFObject *testObj = [query getObjectWithId:@"xWMyZ4YEGZ"];

// ein Array von PFUser "Pointern" (Pointer in Parse-Sprache)
NSLog(@"%@", [testObj objectForKey:@"userArrayProp"]);
[PFObject fetchAll:[testObj objectForKey:@"userArrayProp"]];

// jetzt enthält userArrayProp vollständig abgerufene PFObjects
NSLog(@"%@", [testObj objectForKey:@"userArrayProp"]);

Für mich würde sich userArrayProp nach einer gewissen Zeit wieder in ein Array von "Pointern" zurückverwandeln, und das hat mich verwirrt. Mein Problem war, dass das Aufrufen von refresh auf einem PFObject ein abgerufenes Array wieder in ein Array von Pointern zurückversetzt. So:

PFQuery *query = [PFQuery queryWithClassName:@"TestClass"];
PFObject *testObj = [query getObjectWithId:@"xWMyZ4YEGZ"];

// ein Array von PFUser "Pointern" (Pointer in Parse-Sprache)
NSLog(@"%@", [testObj objectForKey:"userArrayProp"]);
[PFObject fetchAll:[testObj objectForKey:@"userArrayProp"]];

// jetzt enthält userArrayProp vollständig abgerufene PFObjects
NSLog(@"%@", [testObj objectForKey:"userArrayProp"]);

[testObj refresh];

// jetzt enthält auch userArrayProp wieder Pointern :(
NSLog(@"%@", [testObj objectForKey:"userArrayProp"]);

Ich wünschte, es würde in der Dokumentation stehen, dass [PFObject refresh] das macht....

1voto

bklimt Punkte 1792

Was du beschreibst, sollte gut funktionieren. fetchAllIfNeeded aktualisiert die Objekte im Array selbst, daher sollte es nicht darauf ankommen, wie du auf sie zugreifst. Du sagst, dass du über das übergeordnete PFObject auf sie zugreifst, aber die Ausgabe deines Debuggers zeigt den direkten Zugriff über das Array. Ist es möglich, dass das Array nicht auf das aktuelle Mitglied von PFObject zeigt?

Etwas, das du beim Debuggen versuchen könntest, ist isDataAvailable auf den Instanzen von PFUser aufzurufen, sowohl nach dem fetchAllIfNeeded als auch kurz bevor du auf ihre Vornamen und Nachnamen zugreifst. Nach dem Aufruf von fetchAllIfNeeded sollte isDataAvailable für jedes Element des Arrays YES zurückgeben. Wenn es immer noch YES zurückgibt, wenn du auf die Namen zugreifst, sollten sie diesen Fehler nicht verursachen.

Ansonsten, wenn du einen minimalen Codebeispiel bereitstellen kannst, das das Problem reproduziert, helfe ich gerne bei der weiteren Fehlersuche.

Danke,

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X