Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Parse/Internal/Object/PFObjectPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,6 @@
///--------------------------------------
#pragma mark - Data helpers
///--------------------------------------
- (void)checkForChangesToMutableContainers;
- (void)rebuildEstimatedData;

///--------------------------------------
Expand Down
95 changes: 1 addition & 94 deletions Parse/PFObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -79,25 +79,6 @@ static void PFObjectAssertValueIsKindOfValidClass(id object) {
PFParameterAssert(NO, @"PFObject values may not have class: %@", [object class]);
}

/*!
Checks if a class is a of container kind to be used as a value for PFObject.
*/
static BOOL PFObjectValueIsKindOfMutableContainerClass(id object) {
static NSArray *classes;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
classes = @[ [NSDictionary class], [NSArray class], [PFACL class], [PFGeoPoint class] ];
});

for (Class class in classes) {
if ([object isKindOfClass:class]) {
return YES;
}
}

return NO;
}

@interface PFObject () <PFObjectPrivateSubclass> {
// A lock for accessing any of the internal state of this object.
// Guards basically all of the variables below.
Expand Down Expand Up @@ -727,7 +708,6 @@ - (BFTask *)_saveChildrenInBackgroundWithCurrentUser:(PFUser *)currentUser sessi

- (BOOL)isDirty:(BOOL)considerChildren {
@synchronized (lock) {
[self checkForChangesToMutableContainers];
if (self._state.deleted || dirty || [self _hasChanges]) {
return YES;
}
Expand All @@ -754,62 +734,6 @@ - (void)_setDirty:(BOOL)aDirty {
}
}

///--------------------------------------
#pragma mark - Mutable container management
///--------------------------------------

- (void)checkpointAllMutableContainers {
@synchronized (lock) {
[_estimatedData enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
[self checkpointMutableContainer:obj];
}];
}
}

- (void)checkpointMutableContainer:(id)object {
@synchronized (lock) {
if (PFObjectValueIsKindOfMutableContainerClass(object)) {
[hashedObjectsCache setObject:[PFJSONCacheItem cacheFromObject:object]
forKey:[NSValue valueWithNonretainedObject:object]];
}
}
}

- (void)checkForChangesToMutableContainer:(id)object forKey:(NSString *)key {
@synchronized (lock) {
// If this is a mutable container, we should check its contents.
if (PFObjectValueIsKindOfMutableContainerClass(object)) {
PFJSONCacheItem *oldCacheItem = [hashedObjectsCache objectForKey:[NSValue valueWithNonretainedObject:object]];
if (!oldCacheItem) {
[NSException raise:NSInternalInconsistencyException
format:@"PFObject contains container item that isn't cached."];
} else {
PFJSONCacheItem *newCacheItem = [PFJSONCacheItem cacheFromObject:object];
if (![oldCacheItem isEqual:newCacheItem]) {
// A mutable container changed out from under us. Treat it as a set operation.
[self setObject:object forKey:key];
}
}
} else {
[hashedObjectsCache removeObjectForKey:[NSValue valueWithNonretainedObject:object]];
}
}
}

- (void)checkForChangesToMutableContainers {
@synchronized (lock) {
NSMutableArray *unexaminedCacheKeys = [[hashedObjectsCache allKeys] mutableCopy];
NSDictionary *reachableData = _estimatedData.dictionaryRepresentation;
[reachableData enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[unexaminedCacheKeys removeObject:[NSValue valueWithNonretainedObject:obj]];
[self checkForChangesToMutableContainer:obj forKey:key];
}];

// Remove unchecked cache entries.
[hashedObjectsCache removeObjectsForKeys:unexaminedCacheKeys];
}
}

///--------------------------------------
#pragma mark - Data Availability
///--------------------------------------
Expand Down Expand Up @@ -1017,7 +941,6 @@ + (BFTask *)_migrateObjectInBackgroundFromFile:(NSString *)fileName
- (NSDictionary *)RESTDictionaryWithObjectEncoder:(PFEncoder *)objectEncoder
operationSetUUIDs:(NSArray **)operationSetUUIDs {
@synchronized (lock) {
[self checkForChangesToMutableContainers];
PFObjectState *state = self._state;
return [self RESTDictionaryWithObjectEncoder:objectEncoder
operationSetUUIDs:operationSetUUIDs
Expand Down Expand Up @@ -1155,15 +1078,11 @@ - (void)mergeFromRESTDictionary:(NSDictionary *)object withDecoder:(PFDecoder *)
if ([key isEqualToString:PFObjectACLRESTKey]) {
PFACL *acl = [PFACL ACLWithDictionary:obj];
[state setServerDataObject:acl forKey:PFObjectACLRESTKey];
[self checkpointMutableContainer:acl];
return;
}

// Should be decoded
id decodedObject = [decoder decodeObject:obj];
if (PFObjectValueIsKindOfMutableContainerClass(decodedObject)) {
[self checkpointMutableContainer:decodedObject];
}
[state setServerDataObject:decodedObject forKey:key];
}];
if (state.updatedAt == nil && state.createdAt != nil) {
Expand All @@ -1182,7 +1101,6 @@ - (void)mergeFromRESTDictionary:(NSDictionary *)object withDecoder:(PFDecoder *)
}
}
[self rebuildEstimatedData];
[self checkpointAllMutableContainers];
}
}

Expand Down Expand Up @@ -1281,8 +1199,6 @@ - (BFTask *)_enqueueSaveEventuallyOperationAsync:(PFOperationSet *)operationSet
- (NSMutableDictionary *)_convertToDictionaryForSaving:(PFOperationSet *)changes
withObjectEncoder:(PFEncoder *)encoder {
@synchronized (lock) {
[self checkForChangesToMutableContainers];

NSMutableDictionary *serialized = [NSMutableDictionary dictionary];
[changes enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
serialized[key] = obj;
Expand All @@ -1297,12 +1213,11 @@ - (NSMutableDictionary *)_convertToDictionaryForSaving:(PFOperationSet *)changes
*/
- (void)performOperation:(PFFieldOperation *)operation forKey:(NSString *)key {
@synchronized (lock) {
id newValue = [_estimatedData applyFieldOperation:operation forKey:key];
[_estimatedData applyFieldOperation:operation forKey:key];

PFFieldOperation *oldOperation = [[self unsavedChanges] objectForKey:key];
PFFieldOperation *newOperation = [operation mergeWithPrevious:oldOperation];
[[self unsavedChanges] setObject:newOperation forKey:key];
[self checkpointMutableContainer:newValue];
[_availableKeys addObject:key];
}
}
Expand Down Expand Up @@ -1368,7 +1283,6 @@ - (PFObject *)mergeFromObject:(PFObject *)other {
state.updatedAt = other.updatedAt;
state.serverData = [other._state.serverData mutableCopy];
self._state = state;
[self checkpointAllMutableContainers];

dirty = NO;

Expand All @@ -1379,13 +1293,11 @@ - (PFObject *)mergeFromObject:(PFObject *)other {

- (void)_mergeAfterFetchWithResult:(NSDictionary *)result decoder:(PFDecoder *)decoder completeData:(BOOL)completeData {
@synchronized (lock) {
[self checkForChangesToMutableContainers];
[self _mergeFromServerWithResult:result decoder:decoder completeData:completeData];
if (completeData) {
[self removeOldKeysAfterFetch:result];
}
[self rebuildEstimatedData];
[self checkpointAllMutableContainers];
}
}

Expand Down Expand Up @@ -1415,15 +1327,12 @@ - (void)_mergeAfterSaveWithResult:(NSDictionary *)result decoder:(PFDecoder *)de
[operationsForNextSave mergeOperationSet:operationsBeforeSave];
} else {
// Merge the data from the save and the data from the server into serverData.
[self checkForChangesToMutableContainers];

PFMutableObjectState *state = [self._state mutableCopy];
[state applyOperationSet:operationsBeforeSave];
self._state = state;

[self _mergeFromServerWithResult:result decoder:decoder completeData:NO];
[self rebuildEstimatedData];
[self checkpointAllMutableContainers];
}
}
}
Expand All @@ -1445,7 +1354,6 @@ - (void)_mergeFromServerWithResult:(NSDictionary *)result decoder:(PFDecoder *)d
} else if ([key isEqualToString:PFObjectACLRESTKey]) {
PFACL *acl = [PFACL ACLWithDictionary:obj];
[state setServerDataObject:acl forKey:key];
[self checkpointMutableContainer:acl];
} else {
[state setServerDataObject:[decoder decodeObject:obj] forKey:key];
}
Expand Down Expand Up @@ -2089,7 +1997,6 @@ - (BOOL)isDirty {

- (BOOL)isDirtyForKey:(NSString *)key {
@synchronized (lock) {
[self checkForChangesToMutableContainer:_estimatedData[key] forKey:key];
return !![[self unsavedChanges] objectForKey:key];
}
}
Expand Down
3 changes: 0 additions & 3 deletions Parse/PFUser.m
Original file line number Diff line number Diff line change
Expand Up @@ -580,14 +580,11 @@ - (BFTask *)signUpAsync:(BFTask *)toAwait {

PFConsistencyAssert(!isCurrentUser, @"Attempt to merge currentUser with itself.");

[self checkForChangesToMutableContainers];
@synchronized ([currentUser lock]) {
NSString *oldUsername = [currentUser.username copy];
NSString *oldPassword = [currentUser.password copy];
NSArray *oldAnonymousData = currentUser.authData[[PFAnonymousAuthenticationProvider authType]];

[currentUser checkForChangesToMutableContainers];

// Move the changes to this object over to the currentUser object.
PFOperationSet *selfOperations = operationSetQueue[0];
[operationSetQueue removeAllObjects];
Expand Down