Skip to content

Commit

Permalink
Merge branch 'release/0.24.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
segiddins committed Nov 21, 2014
2 parents 07dd102 + 8bab45b commit 3291153
Show file tree
Hide file tree
Showing 56 changed files with 1,570 additions and 748 deletions.
7 changes: 5 additions & 2 deletions Code/CoreData/NSManagedObjectContext+RKAdditions.m
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@ - (BOOL)saveToPersistentStore:(NSError **)error
4. Save the child context to the parent context (the main one) which will work,
5. Save the main context - a NSObjectInaccessibleException will occur and Core Data will either crash your app or lock it up (a semaphore is not correctly released on the first error so the next fetch request will block forever.
*/
[contextToSave obtainPermanentIDsForObjects:[[contextToSave insertedObjects] allObjects] error:&localError];
if (localError) {
__block BOOL obtained;
[contextToSave performBlockAndWait:^{
obtained = [contextToSave obtainPermanentIDsForObjects:[[contextToSave insertedObjects] allObjects] error:&localError];
}];
if (!obtained) {
if (error) *error = localError;
return NO;
}
Expand Down
25 changes: 20 additions & 5 deletions Code/CoreData/RKManagedObjectMappingOperationDataSource.m
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static id RKValueForAttributeMappingInRepresentation(RKAttributeMapping *attribu
__block NSError *error = nil;

// If the representation is mapped with a nesting attribute, we must apply the nesting value to the representation before constructing the identification attributes
RKAttributeMapping *nestingAttributeMapping = [[entityMapping propertyMappingsBySourceKeyPath] objectForKey:RKObjectMappingNestingAttributeKeyName];
RKAttributeMapping *nestingAttributeMapping = [entityMapping mappingForSourceKeyPath:RKObjectMappingNestingAttributeKeyName];
if (nestingAttributeMapping) {
Class attributeClass = [entityMapping classForProperty:nestingAttributeMapping.destinationKeyPath];
id attributeValue = nil;
Expand Down Expand Up @@ -216,6 +216,15 @@ - (void)dealloc
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (id)mappingOperation:(RKMappingOperation *)mappingOperation targetObjectForMapping:(RKObjectMapping *)mapping inRelationship:(RKRelationshipMapping *)relationship
{
if (! [mapping isKindOfClass:[RKEntityMapping class]]) {
return [mapping.objectClass new];
}

return nil;
}

- (id)mappingOperation:(RKMappingOperation *)mappingOperation targetObjectForRepresentation:(NSDictionary *)representation withMapping:(RKObjectMapping *)mapping inRelationship:(RKRelationshipMapping *)relationship
{
NSAssert(representation, @"Mappable data cannot be nil");
Expand Down Expand Up @@ -440,10 +449,11 @@ - (BOOL)mappingOperation:(RKMappingOperation *)mappingOperation deleteExistingVa
- (BOOL)mappingOperationShouldSetUnchangedValues:(RKMappingOperation *)mappingOperation
{
// Only new objects should have a temporary ID
if ([mappingOperation.destinationObject isKindOfClass:[NSManagedObject class]] && [[(NSManagedObject *)mappingOperation.destinationObject objectID] isTemporaryID]) {
return YES;
if ([mappingOperation.destinationObject isKindOfClass:[NSManagedObject class]]) {
return [[(NSManagedObject *)mappingOperation.destinationObject objectID] isTemporaryID];
}
else return NO;

return [mappingOperation isNewDestinationObject];
}

- (BOOL)mappingOperationShouldSkipPropertyMapping:(RKMappingOperation *)mappingOperation
Expand All @@ -456,7 +466,7 @@ - (BOOL)mappingOperationShouldSkipPropertyMapping:(RKMappingOperation *)mappingO
if (! currentValue) return NO;
if (! [currentValue respondsToSelector:@selector(compare:)]) return NO;

RKPropertyMapping *propertyMappingForModificationKey = [[(RKEntityMapping *)mappingOperation.mapping propertyMappingsByDestinationKeyPath] objectForKey:modificationKey];
RKPropertyMapping *propertyMappingForModificationKey = [(RKEntityMapping *)mappingOperation.mapping mappingForDestinationKeyPath:modificationKey];
id rawValue = [[mappingOperation sourceObject] valueForKeyPath:propertyMappingForModificationKey.sourceKeyPath];
if (! rawValue) return NO;
Class attributeClass = [entityMapping classForProperty:propertyMappingForModificationKey.destinationKeyPath];
Expand All @@ -474,4 +484,9 @@ - (BOOL)mappingOperationShouldSkipPropertyMapping:(RKMappingOperation *)mappingO
}
}

- (BOOL)mappingOperationShouldCollectMappingInfo:(RKMappingOperation *)mappingOperation
{
return YES;
}

@end
8 changes: 6 additions & 2 deletions Code/CoreData/RKManagedObjectStore.m
Original file line number Diff line number Diff line change
Expand Up @@ -335,8 +335,12 @@ - (void)recreateManagedObjectContexts

- (BOOL)resetPersistentStores:(NSError **)error
{
[self.mainQueueManagedObjectContext reset];
[self.persistentStoreManagedObjectContext reset];
[self.mainQueueManagedObjectContext performBlockAndWait:^{
[self.mainQueueManagedObjectContext reset];
}];
[self.persistentStoreManagedObjectContext performBlockAndWait:^{
[self.persistentStoreManagedObjectContext reset];
}];

NSError *localError;
for (NSPersistentStore *persistentStore in self.persistentStoreCoordinator.persistentStores) {
Expand Down
63 changes: 38 additions & 25 deletions Code/CoreData/RKPropertyInspector+CoreData.m
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@ - (NSDictionary *)propertyInspectionForEntity:(NSEntityDescription *)entity
if ([cls isSubclassOfClass:[NSNumber class]] && [attributeDescription attributeType] == NSBooleanAttributeType) {
cls = objc_getClass("NSCFBoolean") ?: objc_getClass("__NSCFBoolean") ?: cls;
}
NSDictionary *propertyInspection = @{ RKPropertyInspectionNameKey: name,
RKPropertyInspectionKeyValueCodingClassKey: cls,
RKPropertyInspectionIsPrimitiveKey: @(NO) };
[entityInspection setValue:propertyInspection forKey:name];
RKPropertyInspectorPropertyInfo *info;
info = [RKPropertyInspectorPropertyInfo propertyInfoWithName:name
keyValueClass:cls
isPrimitive:NO];
[entityInspection setValue:info forKey:name];

} else if ([attributeDescription attributeType] == NSTransformableAttributeType &&
![name isEqualToString:@"_mapkit_hasPanoramaID"]) {
Expand All @@ -71,10 +72,11 @@ - (NSDictionary *)propertyInspectionForEntity:(NSEntityDescription *)entity
const char *attr = property_getAttributes(prop);
Class destinationClass = RKKeyValueCodingClassFromPropertyAttributes(attr);
if (destinationClass) {
NSDictionary *propertyInspection = @{ RKPropertyInspectionNameKey: name,
RKPropertyInspectionKeyValueCodingClassKey: destinationClass,
RKPropertyInspectionIsPrimitiveKey: @(NO) };
[entityInspection setObject:propertyInspection forKey:name];
RKPropertyInspectorPropertyInfo *info;
info = [RKPropertyInspectorPropertyInfo propertyInfoWithName:name
keyValueClass:destinationClass
isPrimitive:NO];
[entityInspection setObject:info forKey:name];
}
}
}
Expand All @@ -84,26 +86,29 @@ - (NSDictionary *)propertyInspectionForEntity:(NSEntityDescription *)entity
NSRelationshipDescription *relationshipDescription = [[entity relationshipsByName] valueForKey:name];
if ([relationshipDescription isToMany]) {
if ([relationshipDescription isOrdered]) {
NSDictionary *propertyInspection = @{ RKPropertyInspectionNameKey: name,
RKPropertyInspectionKeyValueCodingClassKey: [NSOrderedSet class],
RKPropertyInspectionIsPrimitiveKey: @(NO) };
[entityInspection setObject:propertyInspection forKey:name];
RKPropertyInspectorPropertyInfo *info;
info = [RKPropertyInspectorPropertyInfo propertyInfoWithName:name
keyValueClass:[NSOrderedSet class]
isPrimitive:NO];
[entityInspection setObject:info forKey:name];
} else {
NSDictionary *propertyInspection = @{ RKPropertyInspectionNameKey: name,
RKPropertyInspectionKeyValueCodingClassKey: [NSSet class],
RKPropertyInspectionIsPrimitiveKey: @(NO) };
[entityInspection setObject:propertyInspection forKey:name];
RKPropertyInspectorPropertyInfo *info;
info = [RKPropertyInspectorPropertyInfo propertyInfoWithName:name
keyValueClass:[NSSet class]
isPrimitive:NO];
[entityInspection setObject:info forKey:name];
}
} else {
NSEntityDescription *destinationEntity = [relationshipDescription destinationEntity];
Class destinationClass = NSClassFromString([destinationEntity managedObjectClassName]);
if (! destinationClass) {
RKLogWarning(@"Retrieved `Nil` value for class named '%@': This likely indicates that the class is invalid or does not exist in the current target.", [destinationEntity managedObjectClassName]);
}
NSDictionary *propertyInspection = @{ RKPropertyInspectionNameKey: name,
RKPropertyInspectionKeyValueCodingClassKey: destinationClass ?: [NSNull null],
RKPropertyInspectionIsPrimitiveKey: @(NO) };
[entityInspection setObject:propertyInspection forKey:name];
RKPropertyInspectorPropertyInfo *info;
info = [RKPropertyInspectorPropertyInfo propertyInfoWithName:name
keyValueClass:destinationClass ?: [NSNull null]
isPrimitive:NO];
[entityInspection setObject:info forKey:name];
}
}

Expand All @@ -117,8 +122,8 @@ - (NSDictionary *)propertyInspectionForEntity:(NSEntityDescription *)entity
- (Class)classForPropertyNamed:(NSString *)propertyName ofEntity:(NSEntityDescription *)entity
{
NSDictionary *entityInspection = [self propertyInspectionForEntity:entity];
NSDictionary *propertyInspection = [entityInspection objectForKey:propertyName];
return [propertyInspection objectForKey:RKPropertyInspectionKeyValueCodingClassKey];
RKPropertyInspectorPropertyInfo *propertyInspection = [entityInspection objectForKey:propertyName];
return propertyInspection.keyValueCodingClass;
}

@end
Expand All @@ -131,13 +136,21 @@ @implementation NSManagedObject (RKPropertyInspection)

- (Class)rk_classForPropertyAtKeyPath:(NSString *)keyPath isPrimitive:(BOOL *)isPrimitive
{
NSArray *components = [keyPath componentsSeparatedByString:@"."];
NSRange dotRange = [keyPath rangeOfString:@"." options:NSLiteralSearch];
RKPropertyInspector *inspector = [RKPropertyInspector sharedInspector];
Class currentPropertyClass = [self class];
Class propertyClass = nil;

if (dotRange.length == 0) {
propertyClass = [inspector classForPropertyNamed:keyPath ofEntity:[self entity]];
return propertyClass ?: [inspector classForPropertyNamed:keyPath ofClass:currentPropertyClass isPrimitive:isPrimitive];
}

NSArray *components = [keyPath componentsSeparatedByString:@"."];
for (NSString *property in components) {
if (isPrimitive) *isPrimitive = NO; // Core Data does not enable you to model primitives
propertyClass = [[RKPropertyInspector sharedInspector] classForPropertyNamed:property ofEntity:[self entity]];
propertyClass = propertyClass ?: [[RKPropertyInspector sharedInspector] classForPropertyNamed:property ofClass:currentPropertyClass isPrimitive:isPrimitive];
propertyClass = [inspector classForPropertyNamed:property ofEntity:[self entity]];
propertyClass = propertyClass ?: [inspector classForPropertyNamed:property ofClass:currentPropertyClass isPrimitive:isPrimitive];
if (! propertyClass) break;
currentPropertyClass = propertyClass;
}
Expand Down
6 changes: 5 additions & 1 deletion Code/CoreData/RKRelationshipConnectionOperation.m
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,11 @@ - (id)findConnectedValueForConnection:(RKConnectionDescription *)connection shou
- (void)main
{
for (RKConnectionDescription *connection in self.connections) {
if (self.isCancelled || [self.managedObject isDeleted]) return;
__block BOOL isDeleted;
[self.managedObject.managedObjectContext performBlockAndWait:^{
isDeleted=[self.managedObject isDeleted];
}];
if (self.isCancelled || isDeleted) return;
NSString *relationshipName = connection.relationship.name;
RKLogTrace(@"Connecting relationship '%@' with mapping: %@", relationshipName, connection);

Expand Down
6 changes: 5 additions & 1 deletion Code/Network/RKManagedObjectRequestOperation.m
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,11 @@ - (BOOL)saveContext:(NSError **)error
}];
}

if ([self.privateContext hasChanges]) {
__block BOOL hasChanges;
[self.privateContext performBlockAndWait:^{
hasChanges = [self.privateContext hasChanges];
}];
if (hasChanges) {
return [self saveContext:self.privateContext error:error];
} else if ([self.targetObject isKindOfClass:[NSManagedObject class]]) {
NSManagedObjectContext *context = [(NSManagedObject *)self.targetObject managedObjectContext];
Expand Down
6 changes: 4 additions & 2 deletions Code/Network/RKObjectRequestOperation.m
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ - (void)HTTPOperationDidFinish:(NSNotification *)notification
NSString *statusCodeAndElapsedTime = statusCodeString ? [NSString stringWithFormat:@"(%ld %@) %@", (long)[operation.response statusCode], statusCodeString, elapsedTimeString] : [NSString stringWithFormat:@"(%ld) %@", (long)[operation.response statusCode], elapsedTimeString];
if (operation.error) {
if ((_RKlcl_component_level[(__RKlcl_log_symbol(RKlcl_cRestKitNetwork))]) >= (__RKlcl_log_symbol(RKlcl_vTrace))) {
RKLogError(@"%@ '%@' %@:\nerror=%@\nresponse.body=%@", [operation.request HTTPMethod], [[operation.request URL] absoluteString], statusCodeAndElapsedTime, operation.error, operation.responseString);
RKLogError(@"%@ '%@' %@:\nerror=%@", [operation.request HTTPMethod], [[operation.request URL] absoluteString], statusCodeAndElapsedTime, operation.error);
RKLogDebug(@"response.body=%@", operation.responseString);
} else {
if (operation.error.code == NSURLErrorCancelled) {
RKLogError(@"%@ '%@' %@: Cancelled", [operation.request HTTPMethod], [[operation.request URL] absoluteString], statusCodeAndElapsedTime);
Expand Down Expand Up @@ -205,7 +206,8 @@ - (void)objectRequestOperationDidFinish:(NSNotification *)notification
NSString *statusCodeAndElapsedTime = [NSString stringWithFormat:@"(%ld%@/ %lu objects) %@", (long)[HTTPRequestOperation.response statusCode], statusCodeDescription, (unsigned long) [objectRequestOperation.mappingResult count], elapsedTimeString];
if (objectRequestOperation.error) {
if ((_RKlcl_component_level[(__RKlcl_log_symbol(RKlcl_cRestKitNetwork))]) >= (__RKlcl_log_symbol(RKlcl_vTrace))) {
RKLogError(@"%@ '%@' %@:\nerror=%@\nresponse.body=%@", [HTTPRequestOperation.request HTTPMethod], [[HTTPRequestOperation.request URL] absoluteString], statusCodeAndElapsedTime, objectRequestOperation.error, HTTPRequestOperation.responseString);
RKLogError(@"%@ '%@' %@:\nerror=%@", [HTTPRequestOperation.request HTTPMethod], [[HTTPRequestOperation.request URL] absoluteString], statusCodeAndElapsedTime, objectRequestOperation.error);
RKLogDebug(@"response.body=%@", HTTPRequestOperation.responseString);
} else {
if (objectRequestOperation.error.code == NSURLErrorCancelled) {
RKLogError(@"%@ '%@' %@: Cancelled", [HTTPRequestOperation.request HTTPMethod], [[HTTPRequestOperation.request URL] absoluteString], statusCodeAndElapsedTime);
Expand Down
22 changes: 20 additions & 2 deletions Code/ObjectMapping/RKDynamicMapping.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

@interface RKDynamicMapping ()
@property (nonatomic, strong) NSMutableArray *mutableMatchers;
@property (nonatomic, strong) NSArray *possibleObjectMappings;
@property (nonatomic, copy) RKObjectMapping *(^objectMappingForRepresentationBlock)(id representation);
@end

Expand All @@ -38,6 +39,7 @@ - (id)init
self = [super init];
if (self) {
self.mutableMatchers = [NSMutableArray new];
self.possibleObjectMappings = [NSArray new];
}

return self;
Expand All @@ -50,7 +52,7 @@ - (NSArray *)matchers

- (NSArray *)objectMappings
{
return [self.mutableMatchers valueForKey:@"objectMapping"];
return self.possibleObjectMappings;
}

- (void)addMatcher:(RKObjectMappingMatcher *)matcher
Expand All @@ -61,13 +63,29 @@ - (void)addMatcher:(RKObjectMappingMatcher *)matcher
[self.mutableMatchers insertObject:matcher atIndex:0];
} else {
[self.mutableMatchers addObject:matcher];

NSArray *newPossibleMappings = [matcher possibleObjectMappings];
if (newPossibleMappings.count > 0) {
self.possibleObjectMappings = [self.possibleObjectMappings arrayByAddingObjectsFromArray:newPossibleMappings];
}
}
}

- (void)removeMatcher:(RKObjectMappingMatcher *)matcher
{
NSParameterAssert(matcher);
[self.mutableMatchers removeObject:matcher];

if ([self.mutableMatchers containsObject:matcher]) {
NSMutableArray *mappings = [self.possibleObjectMappings mutableCopy];
for (RKObjectMapping *mapping in [matcher possibleObjectMappings]) {
/* removeObject will remove *all* instances; if we have dups we just want to remove one */
NSUInteger idx = [mappings indexOfObject:mapping];
if (idx != NSNotFound)
[mappings removeObjectAtIndex:idx];
}
self.possibleObjectMappings = [mappings copy];
[self.mutableMatchers removeObject:matcher];
}
}

- (RKObjectMapping *)objectMappingForRepresentation:(id)representation
Expand Down
Loading

0 comments on commit 3291153

Please sign in to comment.