Reputation: 1805
I have two additional columns on my PFUser "firstName" and "lastName". They are saving properly; I can see the data in the data browser.
I have another PFObject "class" that has a property with a NSArray of PFUsers. I use the class method +fetchAllIfNeededInBackground:block: on PFObject to fetch the array of PFUsers. In the callback block, I call objectForKey: on each of the PFUsers in the array, but I access them through the owning PFObject.
// invited is the NSArray of PFUsers
self.whoCell.mainLabel.text = [[self.plan.invited objectAtIndex:0]
objectForKey:@"firstName"];
Debugger outputs this at a breakpoint right before the objectForKey call:
(lldb) po self.plan.invited
(NSArray *) $4 = 0x06e62a60 <__NSArrayM 0x6e62a60>(
<PFUser:GCCdPjCU2J> {
firstName = Fake;
lastName = Account;
username = yyajnbafv53qw4yhjm9sfoiis;
}
)
Edit: adding implementation of self.plan.invited because the above is misleading.
- (NSArray*)invited
{
// self.dataSource is a PFObject*
return [self.dataSource objectForKey:INVITED_PROP];
}
Yet when the above call it made to objectForKey: this exception is thrown:
'NSInternalInconsistencyException', reason: 'Key "firstName" has no data. Call fetchIfNeeded before getting its value.'
Edit: Accessing the array of fetchedObjects that is passed to the block callback for +fetchAllIfNeededInBackground doesn't throw, but accessing the actual array that was originally passed to +fetchAllIfNeededInBackground throws.
Calling fetchIfNeeded before the call solves the problem, but why? The data is already there. Do I miss understand +fetchAllIfNeededInBackground in that it DOES NOT updated the PFObject that owns to collection of PFUsers?
Upvotes: 2
Views: 3089
Reputation: 1805
I figured out what was happening. Let me explain with code:
PFQuery *query = [PFQuery queryWithClassName:@"TestClass"];
PFObject *testObj = [query getObjectWithId:@"xWMyZ4YEGZ"];
// an array of PFUser "pointers" (pointers in Parse parlance)
NSLog(@"%@", [testObj objectForKey:@"userArrayProp"]);
[PFObject fetchAll:[testObj objectForKey:@"userArrayProp"]];
// now userArrayProp contains fully fetched PFObjects
NSLog(@"%@", [testObj objectForKey:@"userArrayProp"]);
For me, after a certain amount of time userArrayProp would revert to an array of "pointers" and this mystified me. My problem was that calling refresh on a PFObject will revert a fetched array BACK to an array of pointers. Like this:
PFQuery *query = [PFQuery queryWithClassName:@"TestClass"];
PFObject *testObj = [query getObjectWithId:@"xWMyZ4YEGZ"];
// an array of PFUser "pointers" (pointers in Parse parlance)
NSLog(@"%@", [testObj objectForKey:@"userArrayProp"]);
[PFObject fetchAll:[testObj objectForKey:@"userArrayProp"]];
// now userArrayProp contains fully fetched PFObjects
NSLog(@"%@", [testObj objectForKey:@"userArrayProp"]);
[testObj refresh];
// now userArrayProp contains pointers again :(
NSLog(@"%@", [testObj objectForKey:@"userArrayProp"]);
Wish it said that [PFObject refresh]
did that in the documentation....
Upvotes: 6
Reputation: 1842
What you are describing should work fine. fetchAllIfNeeded
updates the objects in the array themselves, so it shouldn't matter how you access them. You say you are accessing them through the parent PFObject
, but your debugger output is showing access through the array directly. Is it possible the array isn't pointing to the current PFObject
member?
One thing you could try while debugging is calling isDataAvailable
on the instances of PFUser
, both after the fetchAllIfNeeded
, and right before you access their first and last names. After the call to fetchAllIfNeeded
, isDataAvailable
should return YES
for every element of the array. If it still returns YES
when you access the names, they should not give this error.
Otherwise, if you can provide a minimal code sample that reproduces the problem, I'd be glad to debug it further.
Thanks,
Upvotes: 1