diff --git a/Parse/Internal/Object/PFObjectPrivate.h b/Parse/Internal/Object/PFObjectPrivate.h index c524df317..4ee8568f2 100644 --- a/Parse/Internal/Object/PFObjectPrivate.h +++ b/Parse/Internal/Object/PFObjectPrivate.h @@ -212,7 +212,6 @@ ///-------------------------------------- #pragma mark - Data helpers ///-------------------------------------- -- (void)checkForChangesToMutableContainers; - (void)rebuildEstimatedData; ///-------------------------------------- diff --git a/Parse/PFObject.m b/Parse/PFObject.m index d2d736c91..6b3ea0581 100644 --- a/Parse/PFObject.m +++ b/Parse/PFObject.m @@ -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 () { // A lock for accessing any of the internal state of this object. // Guards basically all of the variables below. @@ -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; } @@ -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 ///-------------------------------------- @@ -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 @@ -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) { @@ -1182,7 +1101,6 @@ - (void)mergeFromRESTDictionary:(NSDictionary *)object withDecoder:(PFDecoder *) } } [self rebuildEstimatedData]; - [self checkpointAllMutableContainers]; } } @@ -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; @@ -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]; } } @@ -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; @@ -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]; } } @@ -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]; } } } @@ -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]; } @@ -2089,7 +1997,6 @@ - (BOOL)isDirty { - (BOOL)isDirtyForKey:(NSString *)key { @synchronized (lock) { - [self checkForChangesToMutableContainer:_estimatedData[key] forKey:key]; return !![[self unsavedChanges] objectForKey:key]; } } diff --git a/Parse/PFUser.m b/Parse/PFUser.m index 7d88ecaa4..f59e0cc7b 100644 --- a/Parse/PFUser.m +++ b/Parse/PFUser.m @@ -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];