diff --git a/Code/CoreData/RKManagedObjectThreadSafeInvocation.h b/Code/CoreData/RKManagedObjectThreadSafeInvocation.h deleted file mode 100644 index cb4f1534..00000000 --- a/Code/CoreData/RKManagedObjectThreadSafeInvocation.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// RKManagedObjectThreadSafeInvocation.h -// RestKit -// -// Created by Blake Watters on 5/12/11. -// Copyright (c) 2009-2012 RestKit. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -#import - -@interface RKManagedObjectThreadSafeInvocation : NSInvocation - -@property (nonatomic, strong) NSManagedObjectContext *privateQueueManagedObjectContext; -@property (nonatomic, strong) NSManagedObjectContext *mainQueueManagedObjectContext; - -+ (RKManagedObjectThreadSafeInvocation *)invocationWithMethodSignature:(NSMethodSignature *)methodSignature; -- (void)setManagedObjectKeyPaths:(NSSet *)keyPaths forArgument:(NSInteger)index; -- (void)invokeOnMainThread; - -@end diff --git a/Code/CoreData/RKManagedObjectThreadSafeInvocation.m b/Code/CoreData/RKManagedObjectThreadSafeInvocation.m deleted file mode 100644 index e3053614..00000000 --- a/Code/CoreData/RKManagedObjectThreadSafeInvocation.m +++ /dev/null @@ -1,163 +0,0 @@ -// -// RKManagedObjectThreadSafeInvocation.m -// RestKit -// -// Created by Blake Watters on 5/12/11. -// Copyright (c) 2009-2012 RestKit. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -#import "RKManagedObjectThreadSafeInvocation.h" -#import "RKLog.h" - -// Set Logging Component -#undef RKLogComponent -#define RKLogComponent RKlcl_cRestKitCoreData - -@interface RKManagedObjectThreadSafeInvocation () -@property (nonatomic, strong) NSMutableDictionary *argumentKeyPaths; -@end - -@implementation RKManagedObjectThreadSafeInvocation - - -+ (RKManagedObjectThreadSafeInvocation *)invocationWithMethodSignature:(NSMethodSignature *)methodSignature -{ - return (RKManagedObjectThreadSafeInvocation *)[super invocationWithMethodSignature:methodSignature]; -} - -- (void)setManagedObjectKeyPaths:(NSSet *)keyPaths forArgument:(NSInteger)index -{ - if (nil == _argumentKeyPaths) { - self.argumentKeyPaths = [NSMutableDictionary dictionary]; - } - - NSNumber *argumentIndex = [NSNumber numberWithInteger:index]; - [self.argumentKeyPaths setObject:keyPaths forKey:argumentIndex]; -} - -- (void)setValue:(id)value forKeyPathOrKey:(NSString *)keyPath object:(id)object -{ - [object setValue:value forKeyPath:keyPath]; - - id testValue = [object valueForKeyPath:keyPath]; - if (![value isEqual:testValue]) { - [object setValue:value forKey:keyPath]; - testValue = [object valueForKeyPath:keyPath]; - - NSAssert([value isEqual:testValue], @"Could not set value"); - } -} - -- (void)serializeManagedObjectsForArgument:(id)argument withKeyPaths:(NSSet *)keyPaths -{ - for (NSString *keyPath in keyPaths) { - id value = [argument valueForKeyPath:keyPath]; - if ([value isKindOfClass:[NSManagedObject class]]) { - NSManagedObjectID *objectID = [(NSManagedObject *)value objectID]; - [self setValue:objectID forKeyPathOrKey:keyPath object:argument]; - } else if ([value respondsToSelector:@selector(allObjects)]) { - id collection = [[[[value class] alloc] init] mutableCopy]; - for (id subObject in value) { - if ([subObject isKindOfClass:[NSManagedObject class]]) { - [collection addObject:[(NSManagedObject *)subObject objectID]]; - } else { - [collection addObject:subObject]; - } - } - - [self setValue:collection forKeyPathOrKey:keyPath object:argument]; - } - } -} - -- (void)deserializeManagedObjectIDsForArgument:(id)argument withKeyPaths:(NSSet *)keyPaths -{ - NSAssert(self.mainQueueManagedObjectContext, @"Managed object context cannot be nil"); - for (NSString *keyPath in keyPaths) { - id value = [argument valueForKeyPath:keyPath]; - if ([value isKindOfClass:[NSManagedObjectID class]]) { - __block NSManagedObject *managedObject = nil; - __block NSError *error; - [self.mainQueueManagedObjectContext performBlockAndWait:^{ - managedObject = [self.mainQueueManagedObjectContext existingObjectWithID:(NSManagedObjectID *)value error:&error]; - }]; - NSAssert(managedObject, @"Expected managed object for ID %@, got nil", value); - [self setValue:managedObject forKeyPathOrKey:keyPath object:argument]; - } else if ([value respondsToSelector:@selector(allObjects)]) { - id collection = [[[[value class] alloc] init] mutableCopy]; - for (id subObject in value) { - if ([subObject isKindOfClass:[NSManagedObjectID class]]) { - __block NSManagedObject *managedObject = nil; - __block NSError *error; - [self.mainQueueManagedObjectContext performBlockAndWait:^{ - managedObject = [self.mainQueueManagedObjectContext existingObjectWithID:(NSManagedObjectID *)subObject error:&error]; - }]; - NSAssert(managedObject, @"Expected managed object for ID %@, got nil: %@", subObject, error); - [collection addObject:managedObject]; - } else { - [collection addObject:subObject]; - } - } - - - [self setValue:collection forKeyPathOrKey:keyPath object:argument]; - } - } -} - -- (void)serializeManagedObjects -{ - for (NSNumber *argumentIndex in _argumentKeyPaths) { - NSSet *managedKeyPaths = [_argumentKeyPaths objectForKey:argumentIndex]; - id argument = nil; - [self getArgument:&argument atIndex:[argumentIndex intValue]]; - if (argument) { - [self serializeManagedObjectsForArgument:argument withKeyPaths:managedKeyPaths]; - } - } -} - -- (void)deserializeManagedObjects -{ - for (NSNumber *argumentIndex in _argumentKeyPaths) { - NSSet *managedKeyPaths = [_argumentKeyPaths objectForKey:argumentIndex]; - id argument = nil; - [self getArgument:&argument atIndex:[argumentIndex intValue]]; - if (argument) { - [self deserializeManagedObjectIDsForArgument:argument withKeyPaths:managedKeyPaths]; - } - } -} - -- (void)performInvocationOnMainThread -{ - [self deserializeManagedObjects]; - [self invoke]; -} - -- (void)invokeOnMainThread -{ - [self serializeManagedObjects]; - if ([NSThread isMainThread]) { - [self performInvocationOnMainThread]; - } else { - dispatch_sync(dispatch_get_main_queue(), ^{ - [self performInvocationOnMainThread]; - }); - } -} - - -@end diff --git a/Code/Network/RKManagedObjectRequestOperation.h b/Code/Network/RKManagedObjectRequestOperation.h index 1133bd19..80868ce6 100644 --- a/Code/Network/RKManagedObjectRequestOperation.h +++ b/Code/Network/RKManagedObjectRequestOperation.h @@ -46,12 +46,6 @@ Primary key attributes are used in conjunction with the `RKManagedObjectCaching` protocol. Each managed object request operation is associated with an object conforming to the `RKManagedObjectCaching` protocol via the `managedObjectCache` proeprty. This cache is consulted during mapping to find existing objects and when establishing relationships between entities by primary key. Please see the documentation accompanying `RKManagedObjectCaching` and `RKConnectionMapping` for more information. - ## Fetching Result Objects - - When a `completionBlock` is configured for an instance of `RKManagedObjectRequestOperation` additional work is performed before the mapping result is returned to the caller. Because mapping internally occurs on a private managed object context with the `NSPrivateQueueConcurrencyType` concurrency type, attempts to directly access the `NSManagedObject` instances contained within the `RKMappingResult` would violate the threading constraints imposed by Core Data. As such, before the mapping result is returned to the caller in a completion block the objects are re-fetched from the `managedObjectContext`. Please see `RKManagedObjectThreadSafeInvocation` for details about the implementation. - - TODO: Is this necessary? - ## Deleting Managed Objects for `DELETE` requests `RKManagedObjectRequestOperation` adds special behavior to `DELETE` requests. Upon retrieving a successful (2xx status code) response for a `DELETE`, the operation will invoke `deleteObject:` with the operations `targetObject` on the managed object context. This will delete the target object from the local store in conjunction the successfully deleted remote representation. diff --git a/Code/Network/RKManagedObjectRequestOperation.m b/Code/Network/RKManagedObjectRequestOperation.m index 5c584fc8..8811bced 100644 --- a/Code/Network/RKManagedObjectRequestOperation.m +++ b/Code/Network/RKManagedObjectRequestOperation.m @@ -39,13 +39,44 @@ NSFetchRequest *RKFetchRequestFromBlocksWithURL(NSArray *fetchRequestBlocks, NSU return fetchRequest; } +static NSDictionary *RKDictionaryOfManagedObjectsInContextFromDictionaryOfManagedObjects(NSDictionary *dictionaryOfManagedObjects, NSManagedObjectContext *managedObjectContext) +{ + NSMutableDictionary *newDictionary = [[NSMutableDictionary alloc] initWithCapacity:[dictionaryOfManagedObjects count]]; + [managedObjectContext performBlockAndWait:^{ + NSError *error = nil; + for (NSString *key in dictionaryOfManagedObjects) { + id value = dictionaryOfManagedObjects[key]; + if ([value isKindOfClass:[NSArray class]]) { + NSMutableArray *newValue = [[NSMutableArray alloc] initWithCapacity:[value count]]; + for (__strong id object in value) { + if ([object isKindOfClass:[NSManagedObject class]]) { + object = [managedObjectContext existingObjectWithID:[object objectID] error:&error]; + NSCAssert(object, @"Failed to find existing object with ID %@ in context %@: %@", [object objectID], managedObjectContext, error); + } + + [newValue addObject:object]; + } + value = [newValue copy]; + } else if ([value isKindOfClass:[NSManagedObject class]]) { + value = [managedObjectContext existingObjectWithID:[value objectID] error:&error]; + NSCAssert(value, @"Failed to find existing object with ID %@ in context %@: %@", [value objectID], managedObjectContext, error); + } + + [newDictionary setValue:value forKey:key]; + } + }]; + + return newDictionary; +} + @interface RKManagedObjectRequestOperation () // Core Data specific -@property (readwrite, nonatomic, strong) NSManagedObjectContext *privateContext; -@property (readwrite, nonatomic, copy) NSManagedObjectID *targetObjectID; -@property (readwrite, nonatomic, strong) NSMutableDictionary *managedObjectsByKeyPath; -@property (readwrite, nonatomic, strong) NSError *error; +@property (nonatomic, strong) NSManagedObjectContext *privateContext; +@property (nonatomic, copy) NSManagedObjectID *targetObjectID; +@property (nonatomic, strong) NSMutableDictionary *managedObjectsByKeyPath; @property (nonatomic, strong) RKManagedObjectResponseMapperOperation *responseMapperOperation; +@property (nonatomic, strong, readwrite) NSError *error; +@property (nonatomic, strong, readwrite) RKMappingResult *mappingResult; @end @implementation RKManagedObjectRequestOperation @@ -288,6 +319,10 @@ NSFetchRequest *RKFetchRequestFromBlocksWithURL(NSArray *fetchRequestBlocks, NSU } success = [self saveContext:&error]; if (! success) self.error = error; + + // Refetch the mapping results from the externally configured context + NSDictionary *resultsDictionaryFromOriginalContext = RKDictionaryOfManagedObjectsInContextFromDictionaryOfManagedObjects([self.mappingResult dictionary], self.managedObjectContext); + self.mappingResult = [[RKMappingResult alloc] initWithDictionary:resultsDictionaryFromOriginalContext]; } @end diff --git a/RestKit.xcodeproj/project.pbxproj b/RestKit.xcodeproj/project.pbxproj index a22f2800..1749553e 100644 --- a/RestKit.xcodeproj/project.pbxproj +++ b/RestKit.xcodeproj/project.pbxproj @@ -8,6 +8,8 @@ /* Begin PBXBuildFile section */ 0BD827D1939444AF9897B48F /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C8C87FF6727A42D68CA2220E /* libPods.a */; }; + 0D24428768594AB590873733 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DA82BFA2A774416B4AA69A9 /* libPods.a */; }; + 17D2D51D9E864B2F9D9BCED0 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DA82BFA2A774416B4AA69A9 /* libPods.a */; }; 2502C8ED15F79CF70060FD75 /* CoreData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2502C8E715F79CF70060FD75 /* CoreData.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2502C8EE15F79CF70060FD75 /* CoreData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2502C8E715F79CF70060FD75 /* CoreData.h */; }; 2502C8EF15F79CF70060FD75 /* Network.h in Headers */ = {isa = PBXBuildFile; fileRef = 2502C8E815F79CF70060FD75 /* Network.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -77,8 +79,6 @@ 25160DE0145650490060A5C5 /* RKManagedObjectImporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 25160D51145650490060A5C5 /* RKManagedObjectImporter.m */; }; 25160DE1145650490060A5C5 /* RKManagedObjectStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 25160D52145650490060A5C5 /* RKManagedObjectStore.h */; settings = {ATTRIBUTES = (Public, ); }; }; 25160DE2145650490060A5C5 /* RKManagedObjectStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 25160D53145650490060A5C5 /* RKManagedObjectStore.m */; }; - 25160DE3145650490060A5C5 /* RKManagedObjectThreadSafeInvocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 25160D54145650490060A5C5 /* RKManagedObjectThreadSafeInvocation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 25160DE4145650490060A5C5 /* RKManagedObjectThreadSafeInvocation.m in Sources */ = {isa = PBXBuildFile; fileRef = 25160D55145650490060A5C5 /* RKManagedObjectThreadSafeInvocation.m */; }; 25160DE5145650490060A5C5 /* RKPropertyInspector+CoreData.h in Headers */ = {isa = PBXBuildFile; fileRef = 25160D56145650490060A5C5 /* RKPropertyInspector+CoreData.h */; settings = {ATTRIBUTES = (Public, ); }; }; 25160DE6145650490060A5C5 /* RKObjectPropertyInspector+CoreData.m in Sources */ = {isa = PBXBuildFile; fileRef = 25160D57145650490060A5C5 /* RKObjectPropertyInspector+CoreData.m */; }; 25160E09145650490060A5C5 /* RKDynamicMapping.h in Headers */ = {isa = PBXBuildFile; fileRef = 25160D7C145650490060A5C5 /* RKDynamicMapping.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -157,8 +157,6 @@ 25160F74145655D10060A5C5 /* RKManagedObjectImporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 25160D51145650490060A5C5 /* RKManagedObjectImporter.m */; }; 25160F75145655D10060A5C5 /* RKManagedObjectStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 25160D52145650490060A5C5 /* RKManagedObjectStore.h */; settings = {ATTRIBUTES = (Public, ); }; }; 25160F76145655D10060A5C5 /* RKManagedObjectStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 25160D53145650490060A5C5 /* RKManagedObjectStore.m */; }; - 25160F77145655D10060A5C5 /* RKManagedObjectThreadSafeInvocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 25160D54145650490060A5C5 /* RKManagedObjectThreadSafeInvocation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 25160F78145655D10060A5C5 /* RKManagedObjectThreadSafeInvocation.m in Sources */ = {isa = PBXBuildFile; fileRef = 25160D55145650490060A5C5 /* RKManagedObjectThreadSafeInvocation.m */; }; 25160F79145655D10060A5C5 /* RKPropertyInspector+CoreData.h in Headers */ = {isa = PBXBuildFile; fileRef = 25160D56145650490060A5C5 /* RKPropertyInspector+CoreData.h */; settings = {ATTRIBUTES = (Public, ); }; }; 25160F7A145655D10060A5C5 /* RKObjectPropertyInspector+CoreData.m in Sources */ = {isa = PBXBuildFile; fileRef = 25160D57145650490060A5C5 /* RKObjectPropertyInspector+CoreData.m */; }; 25160F7C145657220060A5C5 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 25160F7B145657220060A5C5 /* SystemConfiguration.framework */; }; @@ -177,8 +175,6 @@ 25160F991456576C0060A5C5 /* RKPathMatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 25160DC7145650490060A5C5 /* RKPathMatcher.m */; }; 251610601456F2330060A5C5 /* RKManagedObjectStoreTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25160FCB1456F2330060A5C5 /* RKManagedObjectStoreTest.m */; }; 251610611456F2330060A5C5 /* RKManagedObjectStoreTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25160FCB1456F2330060A5C5 /* RKManagedObjectStoreTest.m */; }; - 251610621456F2330060A5C5 /* RKManagedObjectThreadSafeInvocationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25160FCC1456F2330060A5C5 /* RKManagedObjectThreadSafeInvocationTest.m */; }; - 251610631456F2330060A5C5 /* RKManagedObjectThreadSafeInvocationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25160FCC1456F2330060A5C5 /* RKManagedObjectThreadSafeInvocationTest.m */; }; 251610641456F2330060A5C5 /* blake.png in Resources */ = {isa = PBXBuildFile; fileRef = 25160FCF1456F2330060A5C5 /* blake.png */; }; 251610651456F2330060A5C5 /* blake.png in Resources */ = {isa = PBXBuildFile; fileRef = 25160FCF1456F2330060A5C5 /* blake.png */; }; 251610661456F2330060A5C5 /* ArrayOfNestedDictionaries.json in Resources */ = {isa = PBXBuildFile; fileRef = 25160FD11456F2330060A5C5 /* ArrayOfNestedDictionaries.json */; }; @@ -557,6 +553,7 @@ 25FBB854159272DD00955D27 /* RKRouter.m in Sources */ = {isa = PBXBuildFile; fileRef = 25FBB851159272DD00955D27 /* RKRouter.m */; }; 25FBB855159272DD00955D27 /* RKRouter.m in Sources */ = {isa = PBXBuildFile; fileRef = 25FBB851159272DD00955D27 /* RKRouter.m */; }; 36F3D0E4FD7C4C4AA2B4FEB2 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C8C87FF6727A42D68CA2220E /* libPods.a */; }; + 5738A4C11A81415DBD72C58B /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 04014C1F2EA945798F953D38 /* libPods.a */; }; 5C927E141608FFFD00DC8B07 /* RKDictionaryUtilitiesTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C927E131608FFFD00DC8B07 /* RKDictionaryUtilitiesTest.m */; }; 5C927E151608FFFD00DC8B07 /* RKDictionaryUtilitiesTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C927E131608FFFD00DC8B07 /* RKDictionaryUtilitiesTest.m */; }; 5CCC295615B7124A0045F0F5 /* RKMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CCC295515B7124A0045F0F5 /* RKMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -569,6 +566,7 @@ 73D3907A14CA1DD50093E3D6 /* channels.xml in Resources */ = {isa = PBXBuildFile; fileRef = 73D3907814CA1D710093E3D6 /* channels.xml */; }; 8BC044CA1576CE72003DCDD6 /* RKConnectionMapping.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BC044C81576CE72003DCDD6 /* RKConnectionMapping.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8BC044CB1576CE72003DCDD6 /* RKConnectionMapping.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BC044C91576CE72003DCDD6 /* RKConnectionMapping.m */; }; + AAB37371906649BD90E20FAF /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 04014C1F2EA945798F953D38 /* libPods.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -601,6 +599,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 04014C1F2EA945798F953D38 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 2501405215366000004E0466 /* RKObjectiveCppTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RKObjectiveCppTest.mm; sourceTree = ""; }; 2502C8E715F79CF70060FD75 /* CoreData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreData.h; sourceTree = ""; }; 2502C8E815F79CF70060FD75 /* Network.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Network.h; sourceTree = ""; }; @@ -641,8 +640,6 @@ 25160D51145650490060A5C5 /* RKManagedObjectImporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKManagedObjectImporter.m; sourceTree = ""; }; 25160D52145650490060A5C5 /* RKManagedObjectStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKManagedObjectStore.h; sourceTree = ""; }; 25160D53145650490060A5C5 /* RKManagedObjectStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKManagedObjectStore.m; sourceTree = ""; }; - 25160D54145650490060A5C5 /* RKManagedObjectThreadSafeInvocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKManagedObjectThreadSafeInvocation.h; sourceTree = ""; }; - 25160D55145650490060A5C5 /* RKManagedObjectThreadSafeInvocation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKManagedObjectThreadSafeInvocation.m; sourceTree = ""; }; 25160D56145650490060A5C5 /* RKPropertyInspector+CoreData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RKPropertyInspector+CoreData.h"; sourceTree = ""; }; 25160D57145650490060A5C5 /* RKObjectPropertyInspector+CoreData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RKObjectPropertyInspector+CoreData.m"; sourceTree = ""; }; 25160D7C145650490060A5C5 /* RKDynamicMapping.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKDynamicMapping.h; sourceTree = ""; }; @@ -699,7 +696,6 @@ 25160FC81456F2330060A5C5 /* RKManagedObjectMappingOperationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKManagedObjectMappingOperationTest.m; sourceTree = ""; }; 25160FC91456F2330060A5C5 /* RKEntityMappingTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKEntityMappingTest.m; sourceTree = ""; }; 25160FCB1456F2330060A5C5 /* RKManagedObjectStoreTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKManagedObjectStoreTest.m; sourceTree = ""; }; - 25160FCC1456F2330060A5C5 /* RKManagedObjectThreadSafeInvocationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKManagedObjectThreadSafeInvocationTest.m; sourceTree = ""; }; 25160FCF1456F2330060A5C5 /* blake.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = blake.png; sourceTree = ""; }; 25160FD11456F2330060A5C5 /* ArrayOfNestedDictionaries.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ArrayOfNestedDictionaries.json; sourceTree = ""; }; 25160FD21456F2330060A5C5 /* ArrayOfResults.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ArrayOfResults.json; sourceTree = ""; }; @@ -917,6 +913,7 @@ 41A4EBF715374D1800740BC8 /* redirection.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = redirection.rb; sourceTree = ""; }; 5C927E131608FFFD00DC8B07 /* RKDictionaryUtilitiesTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKDictionaryUtilitiesTest.m; sourceTree = ""; }; 5CCC295515B7124A0045F0F5 /* RKMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKMacros.h; sourceTree = ""; }; + 5DA82BFA2A774416B4AA69A9 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 7394DF3514CF157A00CE7BCE /* RKManagedObjectCaching.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKManagedObjectCaching.h; sourceTree = ""; }; 7394DF3814CF168C00CE7BCE /* RKFetchRequestManagedObjectCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKFetchRequestManagedObjectCache.h; sourceTree = ""; }; 7394DF3914CF168C00CE7BCE /* RKFetchRequestManagedObjectCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKFetchRequestManagedObjectCache.m; sourceTree = ""; }; @@ -928,7 +925,9 @@ 8BC044C81576CE72003DCDD6 /* RKConnectionMapping.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKConnectionMapping.h; sourceTree = ""; }; 8BC044C91576CE72003DCDD6 /* RKConnectionMapping.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKConnectionMapping.m; sourceTree = ""; }; C4123D3CDB2C42AE86B273D7 /* Pods.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.xcconfig; path = Pods/Pods.xcconfig; sourceTree = SOURCE_ROOT; }; + C87136726FCA44FBBC18C515 /* Pods.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.xcconfig; path = Pods/Pods.xcconfig; sourceTree = SOURCE_ROOT; }; C8C87FF6727A42D68CA2220E /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; + E79F34A511E54F35B6580DA7 /* Pods.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.xcconfig; path = Pods/Pods.xcconfig; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -958,6 +957,8 @@ 25160D2A14564E820060A5C5 /* UIKit.framework in Frameworks */, 25160D2B14564E820060A5C5 /* Foundation.framework in Frameworks */, 0BD827D1939444AF9897B48F /* libPods.a in Frameworks */, + 0D24428768594AB590873733 /* libPods.a in Frameworks */, + 5738A4C11A81415DBD72C58B /* libPods.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -981,6 +982,8 @@ 25160E7A145651060060A5C5 /* Cocoa.framework in Frameworks */, 25160E7D145651060060A5C5 /* RestKit.framework in Frameworks */, 36F3D0E4FD7C4C4AA2B4FEB2 /* libPods.a in Frameworks */, + 17D2D51D9E864B2F9D9BCED0 /* libPods.a in Frameworks */, + AAB37371906649BD90E20FAF /* libPods.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1027,6 +1030,8 @@ 25160D1814564E810060A5C5 /* Frameworks */, 25160D1714564E810060A5C5 /* Products */, C4123D3CDB2C42AE86B273D7 /* Pods.xcconfig */, + E79F34A511E54F35B6580DA7 /* Pods.xcconfig */, + C87136726FCA44FBBC18C515 /* Pods.xcconfig */, ); sourceTree = ""; }; @@ -1064,6 +1069,8 @@ 25EC1B0014F8078100C3CF3F /* CoreFoundation.framework */, 25160E65145651060060A5C5 /* Other Frameworks */, C8C87FF6727A42D68CA2220E /* libPods.a */, + 5DA82BFA2A774416B4AA69A9 /* libPods.a */, + 04014C1F2EA945798F953D38 /* libPods.a */, ); name = Frameworks; sourceTree = ""; @@ -1097,8 +1104,6 @@ E4081E0915FB8FD800364948 /* Mapping */, 25160D52145650490060A5C5 /* RKManagedObjectStore.h */, 25160D53145650490060A5C5 /* RKManagedObjectStore.m */, - 25160D54145650490060A5C5 /* RKManagedObjectThreadSafeInvocation.h */, - 25160D55145650490060A5C5 /* RKManagedObjectThreadSafeInvocation.m */, 2597F99A15AF6DC400E547D7 /* RKRelationshipConnectionOperation.h */, 2597F99B15AF6DC400E547D7 /* RKRelationshipConnectionOperation.m */, ); @@ -1284,7 +1289,6 @@ 25160FC81456F2330060A5C5 /* RKManagedObjectMappingOperationTest.m */, 25160FC91456F2330060A5C5 /* RKEntityMappingTest.m */, 25160FCB1456F2330060A5C5 /* RKManagedObjectStoreTest.m */, - 25160FCC1456F2330060A5C5 /* RKManagedObjectThreadSafeInvocationTest.m */, 25E36E0115195CED00F9E448 /* RKFetchRequestMappingCacheTest.m */, 25079C75151B952200266AE7 /* NSEntityDescription+RKAdditionsTest.m */, 25DB7507151BD551009F01AF /* NSManagedObjectContext+RKAdditionsTest.m */, @@ -1673,7 +1677,6 @@ 25160DDB145650490060A5C5 /* RKEntityMapping.h in Headers */, 25160DDF145650490060A5C5 /* RKManagedObjectImporter.h in Headers */, 25160DE1145650490060A5C5 /* RKManagedObjectStore.h in Headers */, - 25160DE3145650490060A5C5 /* RKManagedObjectThreadSafeInvocation.h in Headers */, 25160DE5145650490060A5C5 /* RKPropertyInspector+CoreData.h in Headers */, 25160E09145650490060A5C5 /* RKDynamicMapping.h in Headers */, 25160E0B145650490060A5C5 /* RKErrorMessage.h in Headers */, @@ -1791,7 +1794,6 @@ 25160F6F145655D10060A5C5 /* RKEntityMapping.h in Headers */, 25160F73145655D10060A5C5 /* RKManagedObjectImporter.h in Headers */, 25160F75145655D10060A5C5 /* RKManagedObjectStore.h in Headers */, - 25160F77145655D10060A5C5 /* RKManagedObjectThreadSafeInvocation.h in Headers */, 25160F79145655D10060A5C5 /* RKPropertyInspector+CoreData.h in Headers */, 25160F85145657650060A5C5 /* lcl_config_components_RK.h in Headers */, 25160F86145657650060A5C5 /* lcl_config_extensions_RK.h in Headers */, @@ -1900,6 +1902,8 @@ 25160D2314564E820060A5C5 /* Resources */, 25160D2414564E820060A5C5 /* ShellScript */, F1C99E66F43D4A42AEF2B162 /* Copy Pods Resources */, + A526A94CAA244A79A6DD3C2D /* Copy Pods Resources */, + 1D809DEA215D4BF9A822FD95 /* Copy Pods Resources */, ); buildRules = ( ); @@ -1939,6 +1943,8 @@ 250CA67F147D8EEC0047D347 /* CopyFiles */, 25160E76145651060060A5C5 /* ShellScript */, 91F9BFD4685A46128EAED847 /* Copy Pods Resources */, + 31B1AB25BF2747C7A911C2B2 /* Copy Pods Resources */, + CD932DC245F547468D56D003 /* Copy Pods Resources */, ); buildRules = ( ); @@ -2083,6 +2089,20 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 1D809DEA215D4BF9A822FD95 /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Pods-resources.sh\"\n"; + }; 25160D2414564E820060A5C5 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -2109,6 +2129,20 @@ shellPath = /bin/sh; shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; }; + 31B1AB25BF2747C7A911C2B2 /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Pods-resources.sh\"\n"; + }; 91F9BFD4685A46128EAED847 /* Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -2123,6 +2157,34 @@ shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Pods-resources.sh\"\n"; }; + A526A94CAA244A79A6DD3C2D /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Pods-resources.sh\"\n"; + }; + CD932DC245F547468D56D003 /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Pods-resources.sh\"\n"; + }; F1C99E66F43D4A42AEF2B162 /* Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -2148,7 +2210,6 @@ 25160DDC145650490060A5C5 /* RKEntityMapping.m in Sources */, 25160DE0145650490060A5C5 /* RKManagedObjectImporter.m in Sources */, 25160DE2145650490060A5C5 /* RKManagedObjectStore.m in Sources */, - 25160DE4145650490060A5C5 /* RKManagedObjectThreadSafeInvocation.m in Sources */, 25160DE6145650490060A5C5 /* RKObjectPropertyInspector+CoreData.m in Sources */, 25160E0A145650490060A5C5 /* RKDynamicMapping.m in Sources */, 25160E0C145650490060A5C5 /* RKErrorMessage.m in Sources */, @@ -2231,7 +2292,6 @@ buildActionMask = 2147483647; files = ( 251610601456F2330060A5C5 /* RKManagedObjectStoreTest.m in Sources */, - 251610621456F2330060A5C5 /* RKManagedObjectThreadSafeInvocationTest.m in Sources */, 251610A21456F2330060A5C5 /* Data Model.xcdatamodel in Sources */, 251610A41456F2330060A5C5 /* RKCat.m in Sources */, 251610A61456F2330060A5C5 /* RKChild.m in Sources */, @@ -2308,7 +2368,6 @@ 25160F70145655D10060A5C5 /* RKEntityMapping.m in Sources */, 25160F74145655D10060A5C5 /* RKManagedObjectImporter.m in Sources */, 25160F76145655D10060A5C5 /* RKManagedObjectStore.m in Sources */, - 25160F78145655D10060A5C5 /* RKManagedObjectThreadSafeInvocation.m in Sources */, 25160F7A145655D10060A5C5 /* RKObjectPropertyInspector+CoreData.m in Sources */, 25160F911456576C0060A5C5 /* RKDotNetDateFormatter.m in Sources */, 25160F941456576C0060A5C5 /* RKLog.m in Sources */, @@ -2379,7 +2438,6 @@ buildActionMask = 2147483647; files = ( 251610611456F2330060A5C5 /* RKManagedObjectStoreTest.m in Sources */, - 251610631456F2330060A5C5 /* RKManagedObjectThreadSafeInvocationTest.m in Sources */, 251610A31456F2330060A5C5 /* Data Model.xcdatamodel in Sources */, 251610A51456F2330060A5C5 /* RKCat.m in Sources */, 251610A71456F2330060A5C5 /* RKChild.m in Sources */, @@ -2532,7 +2590,7 @@ }; 25160D3E14564E820060A5C5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C4123D3CDB2C42AE86B273D7 /* Pods.xcconfig */; + baseConfigurationReference = C87136726FCA44FBBC18C515 /* Pods.xcconfig */; buildSettings = { CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_OBJCPP_ARC_ABI = YES; @@ -2540,7 +2598,6 @@ GCC_PREFIX_HEADER = "Code/Support/RestKit-Prefix.pch"; INFOPLIST_FILE = "Resources/PLISTs/RestKitTests-Info.plist"; OBJROOT = "$(SRCROOT)/Build"; - OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SYMROOT = "$(SRCROOT)/Build/Products"; WRAPPER_EXTENSION = octest; @@ -2549,7 +2606,7 @@ }; 25160D3F14564E820060A5C5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C4123D3CDB2C42AE86B273D7 /* Pods.xcconfig */; + baseConfigurationReference = C87136726FCA44FBBC18C515 /* Pods.xcconfig */; buildSettings = { CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_OBJCPP_ARC_ABI = YES; @@ -2557,7 +2614,6 @@ GCC_PREFIX_HEADER = "Code/Support/RestKit-Prefix.pch"; INFOPLIST_FILE = "Resources/PLISTs/RestKitTests-Info.plist"; OBJROOT = "$(SRCROOT)/Build"; - OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SYMROOT = "$(SRCROOT)/Build/Products"; WRAPPER_EXTENSION = octest; @@ -2622,7 +2678,7 @@ }; 25160E8B145651060060A5C5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C4123D3CDB2C42AE86B273D7 /* Pods.xcconfig */; + baseConfigurationReference = C87136726FCA44FBBC18C515 /* Pods.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_ENABLE_OBJC_ARC = YES; @@ -2642,7 +2698,7 @@ }; 25160E8C145651060060A5C5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C4123D3CDB2C42AE86B273D7 /* Pods.xcconfig */; + baseConfigurationReference = C87136726FCA44FBBC18C515 /* Pods.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_ENABLE_OBJC_ARC = YES; diff --git a/RestKit.xcworkspace/contents.xcworkspacedata b/RestKit.xcworkspace/contents.xcworkspacedata index f75a4ef3..5daec31a 100644 --- a/RestKit.xcworkspace/contents.xcworkspacedata +++ b/RestKit.xcworkspace/contents.xcworkspacedata @@ -1,22 +1 @@ - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/Tests/Logic/CoreData/RKManagedObjectThreadSafeInvocationTest.m b/Tests/Logic/CoreData/RKManagedObjectThreadSafeInvocationTest.m deleted file mode 100644 index 611b5452..00000000 --- a/Tests/Logic/CoreData/RKManagedObjectThreadSafeInvocationTest.m +++ /dev/null @@ -1,180 +0,0 @@ -// -// RKManagedObjectThreadSafeInvocationTest.h -// RestKit -// -// Created by Blake Watters on 5/12/11. -// Copyright (c) 2009-2012 RestKit. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -#import "RKTestEnvironment.h" -#import "RKHuman.h" -#import "RKManagedObjectThreadSafeInvocation.h" - -@interface RKManagedObjectThreadSafeInvocation (Private) -- (void)serializeManagedObjectsForArgument:(id)argument withKeyPaths:(NSSet *)keyPaths; -- (void)deserializeManagedObjectIDsForArgument:(id)argument withKeyPaths:(NSSet *)keyPaths; -@end - -@interface RKManagedObjectThreadSafeInvocationTest : RKTestCase { - NSMutableDictionary *_dictionary; - RKManagedObjectStore *_objectStore; - id _results; - BOOL _waiting; -} - -@end - -@implementation RKManagedObjectThreadSafeInvocationTest - -- (void)testShouldSerializeOneManagedObjectToManagedObjectID -{ - RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore]; - RKObjectManager *objectManager = [RKTestFactory objectManager]; - objectManager.managedObjectStore = managedObjectStore; - RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"RKHuman" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext]; - NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObject:human forKey:@"human"]; - NSMethodSignature *signature = [self methodSignatureForSelector:@selector(informDelegateWithDictionary:)]; - RKManagedObjectThreadSafeInvocation *invocation = [RKManagedObjectThreadSafeInvocation invocationWithMethodSignature:signature]; - [invocation serializeManagedObjectsForArgument:dictionary withKeyPaths:[NSSet setWithObject:@"human"]]; - assertThat([dictionary valueForKeyPath:@"human"], is(instanceOf([NSManagedObjectID class]))); -} - -- (void)testShouldSerializeOneManagedObjectWithKeyPathToManagedObjectID -{ - NSString *testKey = @"data.human"; - RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore]; - RKObjectManager *objectManager = [RKTestFactory objectManager]; - objectManager.managedObjectStore = managedObjectStore; - RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"RKHuman" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext]; - NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObject:human forKey:testKey]; - NSMethodSignature *signature = [self methodSignatureForSelector:@selector(informDelegateWithDictionary:)]; - RKManagedObjectThreadSafeInvocation *invocation = [RKManagedObjectThreadSafeInvocation invocationWithMethodSignature:signature]; - [invocation serializeManagedObjectsForArgument:dictionary withKeyPaths:[NSSet setWithObject:testKey]]; - assertThat([dictionary valueForKeyPath:testKey], is(instanceOf([NSManagedObjectID class]))); -} - - -- (void)testShouldSerializeCollectionOfManagedObjectsToManagedObjectIDs -{ - RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore]; - RKObjectManager *objectManager = [RKTestFactory objectManager]; - objectManager.managedObjectStore = managedObjectStore; - RKHuman *human1 = [NSEntityDescription insertNewObjectForEntityForName:@"RKHuman" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext]; - RKHuman *human2 = [NSEntityDescription insertNewObjectForEntityForName:@"RKHuman" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext]; - NSArray *humans = [NSArray arrayWithObjects:human1, human2, nil]; - NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObject:humans forKey:@"humans"]; - NSMethodSignature *signature = [self methodSignatureForSelector:@selector(informDelegateWithDictionary:)]; - RKManagedObjectThreadSafeInvocation *invocation = [RKManagedObjectThreadSafeInvocation invocationWithMethodSignature:signature]; - [invocation serializeManagedObjectsForArgument:dictionary withKeyPaths:[NSSet setWithObject:@"humans"]]; - assertThat([dictionary valueForKeyPath:@"humans"], is(instanceOf([NSArray class]))); - assertThat([[dictionary valueForKeyPath:@"humans"] lastObject], is(instanceOf([NSManagedObjectID class]))); -} - -- (void)testShouldDeserializeOneManagedObjectIDToManagedObject -{ - RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore]; - RKObjectManager *objectManager = [RKTestFactory objectManager]; - objectManager.managedObjectStore = managedObjectStore; - - NSManagedObjectContext *managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; - __block NSError *error; - __block NSManagedObjectID *objectID; - __block NSMutableDictionary *dictionary; - [managedObjectContext performBlockAndWait:^{ - managedObjectContext.parentContext = managedObjectStore.persistentStoreManagedObjectContext; - RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"RKHuman" inManagedObjectContext:managedObjectContext]; - BOOL success = [managedObjectContext obtainPermanentIDsForObjects:[NSArray arrayWithObject:human] error:&error]; - - success = [managedObjectContext save:&error]; - [managedObjectContext.parentContext performBlockAndWait:^{ - [managedObjectContext.parentContext save:&error]; - }]; - assertThatBool(success, is(equalToBool(YES))); - - dictionary = [NSMutableDictionary dictionaryWithObject:[human objectID] forKey:@"human"]; - objectID = human.objectID; - }]; - - [managedObjectStore.mainQueueManagedObjectContext reset]; - NSMethodSignature *signature = [self methodSignatureForSelector:@selector(informDelegateWithDictionary:)]; - RKManagedObjectThreadSafeInvocation* invocation = [RKManagedObjectThreadSafeInvocation invocationWithMethodSignature:signature]; - invocation.privateQueueManagedObjectContext = managedObjectContext; - invocation.mainQueueManagedObjectContext = managedObjectStore.mainQueueManagedObjectContext; - [invocation deserializeManagedObjectIDsForArgument:dictionary withKeyPaths:[NSSet setWithObject:@"human"]]; - assertThat([dictionary valueForKeyPath:@"human"], is(instanceOf([NSManagedObject class]))); - assertThat([[dictionary valueForKeyPath:@"human"] objectID], is(equalTo(objectID))); -} - -- (void)testShouldDeserializeCollectionOfManagedObjectIDToManagedObjects -{ - RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore]; - RKObjectManager *objectManager = [RKTestFactory objectManager]; - objectManager.managedObjectStore = managedObjectStore; - __block NSArray *humanIDs; - [managedObjectStore.persistentStoreManagedObjectContext performBlockAndWait:^{ - RKHuman *human1 = [NSEntityDescription insertNewObjectForEntityForName:@"RKHuman" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext]; - RKHuman *human2 = [NSEntityDescription insertNewObjectForEntityForName:@"RKHuman" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext]; - NSError *error; - BOOL success = [managedObjectStore.persistentStoreManagedObjectContext save:&error]; - assertThatBool(success, is(equalToBool(YES))); - - humanIDs = [NSArray arrayWithObjects:[human1 objectID], [human2 objectID], nil]; - }]; - - NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObject:humanIDs forKey:@"humans"]; - NSMethodSignature *signature = [self methodSignatureForSelector:@selector(informDelegateWithDictionary:)]; - RKManagedObjectThreadSafeInvocation *invocation = [RKManagedObjectThreadSafeInvocation invocationWithMethodSignature:signature]; - invocation.privateQueueManagedObjectContext = managedObjectStore.persistentStoreManagedObjectContext; - invocation.mainQueueManagedObjectContext = managedObjectStore.mainQueueManagedObjectContext; - [invocation deserializeManagedObjectIDsForArgument:dictionary withKeyPaths:[NSSet setWithObject:@"humans"]]; - assertThat([dictionary valueForKeyPath:@"humans"], is(instanceOf([NSArray class]))); - assertThat([dictionary valueForKeyPath:@"humans.objectID"], is(equalTo(humanIDs))); -} - -- (void)informDelegateWithDictionary:(NSDictionary *)results -{ - assertThatBool([NSThread isMainThread], equalToBool(YES)); - assertThat(results, isNot(nilValue())); - assertThat(results, isNot(empty())); - assertThat([[results objectForKey:@"humans"] lastObject], is(instanceOf([NSManagedObject class]))); - _waiting = NO; -} - -- (void)createBackgroundObjects -{ - @autoreleasepool { - assertThatBool([NSThread isMainThread], equalToBool(NO)); - - // Assert this is not the main thread - // Create a new array of objects in the background - RKObjectManager *objectManager = [RKTestFactory objectManager]; - RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore]; - objectManager.managedObjectStore = managedObjectStore; - NSArray *humans = [NSArray arrayWithObject:[NSEntityDescription entityForName:@"RKHuman" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext]]; - _dictionary = [NSMutableDictionary dictionaryWithObject:humans forKey:@"humans"]; - NSMethodSignature *signature = [self methodSignatureForSelector:@selector(informDelegateWithDictionary:)]; - RKManagedObjectThreadSafeInvocation *invocation = [RKManagedObjectThreadSafeInvocation invocationWithMethodSignature:signature]; - invocation.privateQueueManagedObjectContext = _objectStore.persistentStoreManagedObjectContext; - invocation.mainQueueManagedObjectContext = _objectStore.mainQueueManagedObjectContext; - [invocation setTarget:self]; - [invocation setSelector:@selector(informDelegateWithDictionary:)]; - [invocation setArgument:&_dictionary atIndex:2]; // NOTE: _cmd and self are 0 and 1 - [invocation setManagedObjectKeyPaths:[NSSet setWithObject:@"humans"] forArgument:2]; - [invocation invokeOnMainThread]; - - } -} - -@end diff --git a/Tests/Logic/Network/RKManagedObjectRequestOperationTest.m b/Tests/Logic/Network/RKManagedObjectRequestOperationTest.m index fa2c2f78..ff08acea 100644 --- a/Tests/Logic/Network/RKManagedObjectRequestOperationTest.m +++ b/Tests/Logic/Network/RKManagedObjectRequestOperationTest.m @@ -8,6 +8,7 @@ #import "RKTestEnvironment.h" #import "RKManagedObjectRequestOperation.h" +#import "RKEntityMapping.h" @interface RKManagedObjectRequestOperation () - (NSSet *)localObjectsFromFetchRequestsMatchingRequestURL:(NSError **)error; @@ -84,4 +85,24 @@ expect(blockURL.relativeString).to.equal(@"library/"); } +- (void)testThatMappingResultContainsObjectsFetchedFromManagedObjectContextTheOperationWasInitializedWith +{ + // void RKSetIntermediateDictionaryValuesOnObjectForKeyPath(id object, NSString *keyPath); + NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"/JSON/humans/all.json" relativeToURL:[RKTestFactory baseURL]]]; + RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore]; + RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"RKHuman" inManagedObjectStore:managedObjectStore]; + [humanMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"name" toKeyPath:@"name"]]; + + RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:humanMapping pathPattern:nil keyPath:@"human" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]; + RKManagedObjectRequestOperation *managedObjectRequestOperation = [[RKManagedObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[responseDescriptor]]; + managedObjectRequestOperation.managedObjectContext = managedObjectStore.mainQueueManagedObjectContext; + + [managedObjectRequestOperation start]; + [managedObjectRequestOperation waitUntilFinished]; + expect(managedObjectRequestOperation.mappingResult).notTo.beNil(); + NSArray *managedObjectContexts = [[managedObjectRequestOperation.mappingResult array] valueForKeyPath:@"@distinctUnionOfObjects.managedObjectContext"]; + expect([managedObjectContexts count]).to.equal(1); + expect(managedObjectContexts[0]).to.equal(managedObjectStore.mainQueueManagedObjectContext); +} + @end diff --git a/Tests/Logic/ObjectMapping/RKObjectManagerTest.m b/Tests/Logic/ObjectMapping/RKObjectManagerTest.m index 37234fee..06c7d6a8 100644 --- a/Tests/Logic/ObjectMapping/RKObjectManagerTest.m +++ b/Tests/Logic/ObjectMapping/RKObjectManagerTest.m @@ -437,32 +437,35 @@ expect(operation.savesToPersistentStore).to.equal(YES); } -// TODO: Move to Core Data specific spec file... -//- (void)testShouldLoadAHuman -//{ -// -// __block RKObjectRequestOperation *requestOperation = nil; -// [self.objectManager getObjectsAtPath:@"/JSON/humans/1.json" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { -// requestOperation = operation; -// } failure:nil]; -// [self.objectManager.operationQueue waitUntilAllOperationsAreFinished]; -// -// assertThat(loader.error, is(nilValue())); -// assertThat(loader.objects, isNot(empty())); -// RKHuman *blake = (RKHuman *)[loader.objects objectAtIndex:0]; -// assertThat(blake.name, is(equalTo(@"Blake Watters"))); -//} -// -//- (void)testShouldLoadAllHumans -//{ -// RKTestResponseLoader *loader = [RKTestResponseLoader responseLoader]; -// [_objectManager loadObjectsAtResourcePath:@"/JSON/humans/all.json" delegate:loader]; -// [loader waitForResponse]; -// NSArray *humans = (NSArray *)loader.objects; -// assertThatUnsignedInteger([humans count], is(equalToInt(2))); -// assertThat([humans objectAtIndex:0], is(instanceOf([RKHuman class]))); -//} -// +- (void)testShouldLoadAHuman +{ + __block RKObjectRequestOperation *requestOperation = nil; + [self.objectManager getObjectsAtPath:@"/JSON/humans/1.json" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { + requestOperation = operation; + } failure:nil]; + + dispatch_async(dispatch_get_main_queue(), ^{ + expect(requestOperation.error).to.beNil(); + expect([requestOperation.mappingResult array]).notTo.beEmpty(); + RKHuman *blake = (RKHuman *)[requestOperation.mappingResult array][0]; + expect(blake.name).to.equal(@"Blake Watters"); + }); +} + +- (void)testShouldLoadAllHumans +{ + __block RKObjectRequestOperation *requestOperation = nil; + [_objectManager getObjectsAtPath:@"/JSON/humans/all.json" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { + requestOperation = operation; + } failure:nil]; + + dispatch_async(dispatch_get_main_queue(), ^{ + NSArray *humans = [requestOperation.mappingResult array]; + expect(humans).to.haveCountOf(2); + expect(humans[0]).to.beInstanceOf([RKHuman class]); + }); +} + //- (void)testShouldHandleConnectionFailures //{ // NSString *localBaseURL = [NSString stringWithFormat:@"http://127.0.0.1:3001"]; @@ -675,38 +678,5 @@ // [responseLoader waitForResponse]; //} // -//- (void)testThatInitializationOfObjectManagerInitializesNetworkStatusFromClient -//{ -// RKReachabilityObserver *observer = [[RKReachabilityObserver alloc] initWithHost:@"google.com"]; -// id mockObserver = [OCMockObject partialMockForObject:observer]; -// BOOL yes = YES; -// [[[mockObserver stub] andReturnValue:OCMOCK_VALUE(yes)] isReachabilityDetermined]; -// [[[mockObserver stub] andReturnValue:OCMOCK_VALUE(yes)] isNetworkReachable]; -// RKClient *client = [RKTestFactory client]; -// client.reachabilityObserver = mockObserver; -// RKObjectManager *manager = [[RKObjectManager alloc] init]; -// manager.client = client; -// assertThatInteger(manager.networkStatus, is(equalToInteger(RKObjectManagerNetworkStatusOnline))); -//} -// -//- (void)testThatMutationOfUnderlyingClientReachabilityObserverUpdatesManager -//{ -// RKObjectManager *manager = [RKTestFactory objectManager]; -// RKReachabilityObserver *observer = [[RKReachabilityObserver alloc] initWithHost:@"google.com"]; -// assertThatInteger(manager.networkStatus, is(equalToInteger(RKObjectManagerNetworkStatusOnline))); -// manager.client.reachabilityObserver = observer; -// assertThatInteger(manager.networkStatus, is(equalToInteger(RKObjectManagerNetworkStatusUnknown))); -// -// -//- (void)testThatReplacementOfUnderlyingClientUpdatesManagerReachabilityObserver -//{ -// RKObjectManager *manager = [RKTestFactory objectManager]; -// RKReachabilityObserver *observer = [[RKReachabilityObserver alloc] initWithHost:@"google.com"]; -// RKClient *client = [RKTestFactory client]; -// client.reachabilityObserver = observer; -// assertThatInteger(manager.networkStatus, is(equalToInteger(RKObjectManagerNetworkStatusOnline))); -// manager.client = client; -// assertThatInteger(manager.networkStatus, is(equalToInteger(RKObjectManagerNetworkStatusUnknown))); -//} @end