diff --git a/Parse/PFObject.h b/Parse/PFObject.h index df271f2cb..ba829e0e1 100644 --- a/Parse/PFObject.h +++ b/Parse/PFObject.h @@ -141,7 +141,7 @@ NS_REQUIRES_PROPERTY_DEFINITIONS /*! @abstract Sets the object associated with a given key. - @param object The object for `key`. A strong reference to the object is maintaned by PFObject. + @param object The object for `key`. A strong reference to the object is maintained by PFObject. Raises an `NSInvalidArgumentException` if `object` is `nil`. If you need to represent a `nil` value - use `NSNull`. @param key The key for `object`. @@ -176,7 +176,7 @@ NS_REQUIRES_PROPERTY_DEFINITIONS @discussion This method enables usage of literal syntax on `PFObject`. E.g. `object[@"key"] = @"value";` - @param object The object for `key`. A strong reference to the object is maintaned by PFObject. + @param object The object for `key`. A strong reference to the object is maintained by PFObject. Raises an `NSInvalidArgumentException` if `object` is `nil`. If you need to represent a `nil` value - use `NSNull`. @param key The key for `object`. @@ -202,6 +202,19 @@ NS_REQUIRES_PROPERTY_DEFINITIONS */ - (PFRelation *)relationforKey:(NSString *)key PARSE_DEPRECATED("Please use -relationForKey: instead."); +/*! + @abstract Clears any changes to this object made since the last call to save and sets it back to the server state. + */ +- (void)revert; + +/*! + @abstract Clears any changes to this object's key that were done after last successful save and sets it back to the + server state. + + @param key The key to revert changes for. + */ +- (void)revertObjectForKey:(NSString *)key; + ///-------------------------------------- /// @name Array Accessors ///-------------------------------------- diff --git a/Parse/PFObject.m b/Parse/PFObject.m index 258c99c10..b49658184 100644 --- a/Parse/PFObject.m +++ b/Parse/PFObject.m @@ -2313,6 +2313,38 @@ - (void)removeObjectForKey:(NSString *)key { } } +- (void)revert { + @synchronized (self.lock) { + if ([self isDirty]) { + NSMutableSet *persistentKeys = [NSMutableSet setWithArray:[self._state.serverData allKeys]]; + + PFOperationSet *unsavedChanges = [self unsavedChanges]; + for (PFOperationSet *operationSet in operationSetQueue) { + if (operationSet != unsavedChanges) { + [persistentKeys addObjectsFromArray:[operationSet.keyEnumerator allObjects]]; + } + } + + [unsavedChanges removeAllObjects]; + [_availableKeys intersectSet:persistentKeys]; + + [self rebuildEstimatedData]; + [self checkpointAllMutableContainers]; + } + } +} + +- (void)revertObjectForKey:(NSString *)key { + @synchronized (self.lock) { + if ([self isDirtyForKey:key]) { + [[self unsavedChanges] removeObjectForKey:key]; + [self rebuildEstimatedData]; + [_availableKeys removeObject:key]; + [self checkpointAllMutableContainers]; + } + } +} + #pragma mark Relations - (PFRelation *)relationforKey:(NSString *)key { diff --git a/Tests/Unit/ObjectUnitTests.m b/Tests/Unit/ObjectUnitTests.m index 18f99bd5e..2b9e7dadf 100644 --- a/Tests/Unit/ObjectUnitTests.m +++ b/Tests/Unit/ObjectUnitTests.m @@ -10,6 +10,7 @@ #import "PFObject.h" #import "PFUnitTestCase.h" #import "Parse_Private.h" +#import "PFObjectPrivate.h" @interface ObjectUnitTests : PFUnitTestCase @@ -186,7 +187,7 @@ - (void)testKeyValueCoding { - (void)testFetchObjectWithoutObjectIdError { PFObject *object = [PFObject objectWithClassName:@"Test"]; - + XCTestExpectation *expectation = [self currentSelectorTestExpectation]; [[object fetchInBackground] continueWithBlock:^id(BFTask *task) { XCTAssertNotNil(task.error); @@ -198,4 +199,31 @@ - (void)testFetchObjectWithoutObjectIdError { [self waitForTestExpectations]; } +#pragma mark Revert + +- (void)testRevert { + NSDate *date = [NSDate date]; + NSNumber *number = @0.75; + PFObject *object = [PFObject _objectFromDictionary:@{ @"yarr" : date, + @"score": number } + defaultClassName:@"Test" completeData:YES]; + object[@"yarr"] = @"yolo"; + [object revert]; + XCTAssertEqualObjects(object[@"yarr"], date); + XCTAssertEqualObjects(object[@"score"], number); +} + +- (void)testRevertObjectForKey { + NSDate *date = [NSDate date]; + NSNumber *number = @0.75; + PFObject *object = [PFObject _objectFromDictionary:@{ @"yarr" : date, + @"score" : @1.0 } + defaultClassName:@"Test" completeData:YES]; + object[@"yarr"] = @"yolo"; + object[@"score"] = number; + [object revertObjectForKey:@"yarr"]; + XCTAssertEqualObjects(object[@"yarr"], date); + XCTAssertEqualObjects(object[@"score"], number); +} + @end