Skip to content

Commit 24f116c

Browse files
author
Blake Watters
committed
Merge branch 'release/0.21.0'
2 parents c082a8f + 1562978 commit 24f116c

File tree

97 files changed

+2077
-1875
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+2077
-1875
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,7 @@ Pods
2828
RestKit.xcodeproj/xcshareddata/
2929
RestKit.xcworkspace/xcshareddata/xcschemes/
3030
DerivedData
31+
32+
# Bundler binstubs
33+
.bundle
34+
bin

.gitmodules

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,9 @@
44
[submodule "Vendor/TransitionKit"]
55
path = Vendor/TransitionKit
66
url = https://github.com/blakewatters/TransitionKit.git
7+
[submodule "Vendor/RKValueTransformers"]
8+
path = Vendor/RKValueTransformers
9+
url = https://github.com/RestKit/RKValueTransformers.git
10+
[submodule "Vendor/ISO8601DateFormatterValueTransformer"]
11+
path = Vendor/ISO8601DateFormatterValueTransformer
12+
url = https://github.com/blakewatters/ISO8601DateFormatterValueTransformer.git

.ruby-gemset

Lines changed: 0 additions & 1 deletion
This file was deleted.

.ruby-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
ruby-1.9.3-p429
1+
1.9.3-p429

.travis.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
language: objective-c
22
before_install:
33
- brew update
4-
- brew install xctool --HEAD
5-
- bundle install
4+
- brew uninstall xctool
5+
- brew install xctool
66
script:
7-
- rake server:start
8-
- rake test
7+
- rake server:start test test:building_without_core_data
8+

Code/CoreData/RKManagedObjectMappingOperationDataSource.m

Lines changed: 36 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,10 @@
3636

3737
extern NSString * const RKObjectMappingNestingAttributeKeyName;
3838

39-
static char kRKManagedObjectMappingOperationDataSourceAssociatedObjectKey;
39+
static void *RKManagedObjectMappingOperationDataSourceAssociatedObjectKey = &RKManagedObjectMappingOperationDataSourceAssociatedObjectKey;
4040

41-
id RKTransformedValueWithClass(id value, Class destinationType, NSValueTransformer *dateToStringValueTransformer);
4241
NSArray *RKApplyNestingAttributeValueToMappings(NSString *attributeName, id value, NSArray *propertyMappings);
4342

44-
// Return YES if the entity is identified by an attribute that acts as the nesting key in the source representation
45-
static BOOL RKEntityMappingIsIdentifiedByNestingAttribute(RKEntityMapping *entityMapping)
46-
{
47-
for (NSAttributeDescription *attribute in [entityMapping identificationAttributes]) {
48-
RKAttributeMapping *attributeMapping = [[entityMapping propertyMappingsByDestinationKeyPath] objectForKey:[attribute name]];
49-
if ([attributeMapping.sourceKeyPath isEqualToString:RKObjectMappingNestingAttributeKeyName]) {
50-
return YES;
51-
}
52-
}
53-
54-
return NO;
55-
}
56-
5743
static id RKValueForAttributeMappingInRepresentation(RKAttributeMapping *attributeMapping, NSDictionary *representation)
5844
{
5945
if ([attributeMapping.sourceKeyPath isEqualToString:RKObjectMappingNestingAttributeKeyName]) {
@@ -81,16 +67,15 @@ static id RKValueForAttributeMappingInRepresentation(RKAttributeMapping *attribu
8167
{
8268
NSCParameterAssert(entityMapping);
8369
NSCAssert([representation isKindOfClass:[NSDictionary class]], @"Expected a dictionary representation");
84-
85-
RKDateToStringValueTransformer *dateToStringTransformer = [[RKDateToStringValueTransformer alloc] initWithDateToStringFormatter:entityMapping.preferredDateFormatter
86-
stringToDateFormatters:entityMapping.dateFormatters];
8770
NSArray *attributeMappings = entityMapping.attributeMappings;
88-
71+
__block NSError *error = nil;
72+
8973
// If the representation is mapped with a nesting attribute, we must apply the nesting value to the representation before constructing the identification attributes
9074
RKAttributeMapping *nestingAttributeMapping = [[entityMapping propertyMappingsBySourceKeyPath] objectForKey:RKObjectMappingNestingAttributeKeyName];
9175
if (nestingAttributeMapping) {
9276
Class attributeClass = [entityMapping classForProperty:nestingAttributeMapping.destinationKeyPath];
93-
id attributeValue = RKTransformedValueWithClass([[representation allKeys] lastObject], attributeClass, dateToStringTransformer);
77+
id attributeValue = nil;
78+
[entityMapping.valueTransformer transformValue:[[representation allKeys] lastObject] toValue:&attributeValue ofClass:attributeClass error:&error];
9479
attributeMappings = RKApplyNestingAttributeValueToMappings(nestingAttributeMapping.destinationKeyPath, attributeValue, attributeMappings);
9580
}
9681

@@ -100,7 +85,8 @@ static id RKValueForAttributeMappingInRepresentation(RKAttributeMapping *attribu
10085
RKAttributeMapping *attributeMapping = RKAttributeMappingForNameInMappings([attribute name], attributeMappings);
10186
Class attributeClass = [entityMapping classForProperty:[attribute name]];
10287
id sourceValue = RKValueForAttributeMappingInRepresentation(attributeMapping, representation);
103-
id attributeValue = RKTransformedValueWithClass(sourceValue, attributeClass, dateToStringTransformer);
88+
id attributeValue = nil;
89+
if (sourceValue) [entityMapping.valueTransformer transformValue:sourceValue toValue:&attributeValue ofClass:attributeClass error:&error];
10490
[entityIdentifierAttributes setObject:attributeValue ?: [NSNull null] forKey:[attribute name]];
10591
}];
10692

@@ -253,7 +239,7 @@ - (id)mappingOperation:(RKMappingOperation *)mappingOperation targetObjectForRep
253239
id existingObjectsOfRelationship = identificationAttributes ? [mappingOperation.destinationObject valueForKeyPath:relationship.destinationKeyPath] : RKMutableCollectionValueWithObjectForKeyPath(mappingOperation.destinationObject, relationship.destinationKeyPath);
254240
if (existingObjectsOfRelationship && !RKObjectIsCollection(existingObjectsOfRelationship)) existingObjectsOfRelationship = @[ existingObjectsOfRelationship ];
255241
for (NSManagedObject *existingObject in existingObjectsOfRelationship) {
256-
if (! identificationAttributes) {
242+
if (! identificationAttributes && ![existingObject isDeleted]) {
257243
managedObject = existingObject;
258244
[existingObjectsOfRelationship removeObject:managedObject];
259245
break;
@@ -341,9 +327,10 @@ - (BOOL)commitChangesForMappingOperation:(RKMappingOperation *)mappingOperation
341327
// Add a dependency on the parent operation. If we are being mapped as part of a relationship, then the assignment of the mapped object to a parent may well fulfill the validation requirements. This ensures that the relationship mapping has completed before we evaluate the object for deletion.
342328
if (self.parentOperation) [deletionOperation addDependency:self.parentOperation];
343329

330+
RKRelationshipConnectionOperation *connectionOperation = nil;
344331
if ([connections count]) {
345-
RKRelationshipConnectionOperation *operation = [[RKRelationshipConnectionOperation alloc] initWithManagedObject:mappingOperation.destinationObject connections:connections managedObjectCache:self.managedObjectCache];
346-
[operation setConnectionBlock:^(RKRelationshipConnectionOperation *operation, RKConnectionDescription *connection, id connectedValue) {
332+
connectionOperation = [[RKRelationshipConnectionOperation alloc] initWithManagedObject:mappingOperation.destinationObject connections:connections managedObjectCache:self.managedObjectCache];
333+
[connectionOperation setConnectionBlock:^(RKRelationshipConnectionOperation *operation, RKConnectionDescription *connection, id connectedValue) {
347334
if (connectedValue) {
348335
if ([mappingOperation.delegate respondsToSelector:@selector(mappingOperation:didConnectRelationship:toValue:usingConnection:)]) {
349336
[mappingOperation.delegate mappingOperation:mappingOperation didConnectRelationship:connection.relationship toValue:connectedValue usingConnection:connection];
@@ -355,34 +342,35 @@ - (BOOL)commitChangesForMappingOperation:(RKMappingOperation *)mappingOperation
355342
}
356343
}];
357344

358-
if (self.parentOperation) [operation addDependency:self.parentOperation];
359-
[deletionOperation addDependency:operation];
360-
[operationQueue addOperation:operation];
361-
RKLogTrace(@"Enqueued %@ dependent upon parent operation %@ to operation queue %@", operation, self.parentOperation, operationQueue);
345+
if (self.parentOperation) [connectionOperation addDependency:self.parentOperation];
346+
[deletionOperation addDependency:connectionOperation];
347+
[operationQueue addOperation:connectionOperation];
348+
RKLogTrace(@"Enqueued %@ dependent upon parent operation %@ to operation queue %@", connectionOperation, self.parentOperation, operationQueue);
362349
}
363350

364351
// Enqueue our deletion operation for execution after all the connections
365352
[operationQueue addOperation:deletionOperation];
366353

367354
// Handle tombstone deletion by predicate
368355
if ([(RKEntityMapping *)mappingOperation.objectMapping deletionPredicate]) {
369-
RKManagedObjectDeletionOperation *deletionOperation = nil;
370-
if (self.parentOperation) {
356+
RKManagedObjectDeletionOperation *predicateDeletionOperation = nil;
357+
// Attach a deletion operation for execution after the parent operation completes
358+
predicateDeletionOperation = (RKManagedObjectDeletionOperation *)objc_getAssociatedObject(self.parentOperation, RKManagedObjectMappingOperationDataSourceAssociatedObjectKey);
359+
if (! predicateDeletionOperation) {
360+
predicateDeletionOperation = [[RKManagedObjectDeletionOperation alloc] initWithManagedObjectContext:self.managedObjectContext];
361+
371362
// Attach a deletion operation for execution after the parent operation completes
372-
deletionOperation = (RKManagedObjectDeletionOperation *)objc_getAssociatedObject(self.parentOperation, &kRKManagedObjectMappingOperationDataSourceAssociatedObjectKey);
373-
if (! deletionOperation) {
374-
deletionOperation = [[RKManagedObjectDeletionOperation alloc] initWithManagedObjectContext:self.managedObjectContext];
375-
objc_setAssociatedObject(self.parentOperation, &kRKManagedObjectMappingOperationDataSourceAssociatedObjectKey, deletionOperation, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
376-
[deletionOperation addDependency:self.parentOperation];
377-
NSOperationQueue *operationQueue = self.operationQueue ?: [NSOperationQueue currentQueue];
378-
[operationQueue addOperation:deletionOperation];
363+
if (self.parentOperation) {
364+
objc_setAssociatedObject(self.parentOperation, RKManagedObjectMappingOperationDataSourceAssociatedObjectKey, predicateDeletionOperation, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
365+
[predicateDeletionOperation addDependency:self.parentOperation];
379366
}
380-
[deletionOperation addEntityMapping:(RKEntityMapping *)mappingOperation.objectMapping];
381-
} else {
382-
deletionOperation = [[RKManagedObjectDeletionOperation alloc] initWithManagedObjectContext:self.managedObjectContext];
383-
[deletionOperation addEntityMapping:(RKEntityMapping *)mappingOperation.objectMapping];
384-
[deletionOperation start];
367+
368+
// Ensure predicate deletion executes after any connections have been established
369+
if (connectionOperation) [predicateDeletionOperation addDependency:connectionOperation];
370+
371+
[operationQueue addOperation:predicateDeletionOperation];
385372
}
373+
[predicateDeletionOperation addEntityMapping:(RKEntityMapping *)mappingOperation.objectMapping];
386374
}
387375
}
388376

@@ -423,7 +411,7 @@ - (void)updateCacheWithChangesFromContextWillSaveNotification:(NSNotification *)
423411
- (BOOL)mappingOperation:(RKMappingOperation *)mappingOperation deleteExistingValueOfRelationshipWithMapping:(RKRelationshipMapping *)relationshipMapping error:(NSError **)error
424412
{
425413
// Validate the assignment policy
426-
if (! relationshipMapping.assignmentPolicy == RKReplaceAssignmentPolicy) {
414+
if (relationshipMapping.assignmentPolicy != RKReplaceAssignmentPolicy) {
427415
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"Unable to satisfy deletion request: Relationship mapping was expected to have an assignment policy of `RKReplaceAssignmentPolicy`, but did not." };
428416
NSError *localError = [NSError errorWithDomain:RKErrorDomain code:RKMappingErrorInvalidAssignmentPolicy userInfo:userInfo];
429417
if (error) *error = localError;
@@ -466,10 +454,12 @@ - (BOOL)mappingOperationShouldSkipPropertyMapping:(RKMappingOperation *)mappingO
466454
if (! [currentValue respondsToSelector:@selector(compare:)]) return NO;
467455

468456
RKPropertyMapping *propertyMappingForModificationKey = [[(RKEntityMapping *)mappingOperation.mapping propertyMappingsByDestinationKeyPath] objectForKey:modificationKey];
469-
id rawValue = [[mappingOperation sourceObject] valueForKeyPath:propertyMappingForModificationKey.sourceKeyPath];
470-
RKDateToStringValueTransformer *transformer = [[RKDateToStringValueTransformer alloc] initWithDateToStringFormatter:entityMapping.preferredDateFormatter stringToDateFormatters:entityMapping.dateFormatters];
457+
id rawValue = [[mappingOperation sourceObject] valueForKeyPath:propertyMappingForModificationKey.sourceKeyPath];
471458
Class attributeClass = [entityMapping classForProperty:propertyMappingForModificationKey.destinationKeyPath];
472-
id transformedValue = RKTransformedValueWithClass(rawValue, attributeClass, transformer);
459+
460+
id transformedValue = nil;
461+
NSError *error = nil;
462+
[entityMapping.valueTransformer transformValue:rawValue toValue:&transformedValue ofClass:attributeClass error:&error];
473463
if (! transformedValue) return NO;
474464

475465
if ([currentValue isKindOfClass:[NSString class]]) {

Code/CoreData/RKManagedObjectStore.m

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,24 @@ - (BOOL)copySeedDatabaseIfNecessaryFromPath:(NSString *)seedPath toPath:(NSStrin
245245

246246
return NO;
247247
}
248+
if ([[NSFileManager defaultManager] fileExistsAtPath:[seedPath stringByAppendingString:@"-shm"]]) {
249+
if (![[NSFileManager defaultManager] copyItemAtPath:[seedPath stringByAppendingString:@"-shm"] toPath:[storePath stringByAppendingString:@"-shm"] error:&localError]) {
250+
RKLogError(@"Failed to copy seed database (SHM) from path '%@' to path '%@': %@", seedPath, storePath, [localError localizedDescription]);
251+
if (error) *error = localError;
252+
253+
return NO;
254+
}
255+
}
256+
if ([[NSFileManager defaultManager] fileExistsAtPath:[seedPath stringByAppendingString:@"-wal"]]) {
257+
if (![[NSFileManager defaultManager] copyItemAtPath:[seedPath stringByAppendingString:@"-wal"] toPath:[storePath stringByAppendingString:@"-wal"] error:&localError]) {
258+
RKLogError(@"Failed to copy seed database (WAL) from path '%@' to path '%@': %@", seedPath, storePath, [localError localizedDescription]);
259+
if (error) *error = localError;
260+
261+
return NO;
262+
}
263+
}
248264
}
249-
265+
250266
return YES;
251267
}
252268

@@ -342,6 +358,19 @@ - (BOOL)resetPersistentStores:(NSError **)error
342358
RKLogWarning(@"Found external support item for store at path that is not a directory: %@", [supportDirectoryFileURL path]);
343359
}
344360
}
361+
362+
// Check for and remove -shm and -wal files
363+
for (NSString *suffix in @[ @"-shm", @"-wal" ]) {
364+
NSString *supportFileName = [[URL lastPathComponent] stringByAppendingString:suffix];
365+
NSURL *supportFileURL = [NSURL URLWithString:supportFileName relativeToURL:[URL URLByDeletingLastPathComponent]];
366+
if ([[NSFileManager defaultManager] fileExistsAtPath:[supportFileURL path]]) {
367+
if (! [[NSFileManager defaultManager] removeItemAtURL:supportFileURL error:&localError]) {
368+
RKLogError(@"Failed to remove support file at URL %@: %@", supportFileURL, localError);
369+
if (error) *error = localError;
370+
return NO;
371+
}
372+
}
373+
}
345374
} else {
346375
RKLogDebug(@"Skipped removal of persistent store file: URL for persistent store is not a file URL. (%@)", URL);
347376
}

Code/Network.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,8 @@
2525
#import "RKResponseDescriptor.h"
2626
#import "RKObjectManager.h"
2727
#import "RKHTTPUtilities.h"
28+
#import "RKObjectRequestOperation.h"
29+
30+
#ifdef _COREDATADEFINES_H
31+
#import "RKManagedObjectRequestOperation.h"
32+
#endif

Code/Network/RKHTTPRequestOperation.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
// limitations under the License.
1919
//
2020

21-
#import "AFNetworking.h"
21+
#import "AFHTTPClient.h"
2222
#import "AFHTTPRequestOperation.h"
2323

2424
// Expose the default headers from AFNetworking's AFHTTPClient

Code/Network/RKHTTPRequestOperation.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@
3232

3333
NSString *RKStringFromIndexSet(NSIndexSet *indexSet); // Defined in RKResponseDescriptor.m
3434

35+
static BOOL RKResponseRequiresContentTypeMatch(NSHTTPURLResponse *response, NSURLRequest *request)
36+
{
37+
if (RKRequestMethodFromString(request.HTTPMethod) == RKRequestMethodHEAD) return NO;
38+
if (response.statusCode == 304) return NO;
39+
if (response.statusCode == 204) return NO;
40+
return YES;
41+
}
42+
3543
@interface AFURLConnectionOperation () <NSURLConnectionDataDelegate>
3644
@property (readwrite, nonatomic, strong) NSRecursiveLock *lock;
3745
@end
@@ -68,6 +76,7 @@ - (BOOL)hasAcceptableStatusCode
6876
- (BOOL)hasAcceptableContentType
6977
{
7078
if (! self.response) return NO;
79+
if (!RKResponseRequiresContentTypeMatch(self.response, self.request)) return YES;
7180
NSString *contentType = [self.response MIMEType] ?: @"application/octet-stream";
7281
return self.acceptableContentTypes ? RKMIMETypeInSet(contentType, self.acceptableContentTypes) : [super hasAcceptableContentType];
7382
}

Code/Network/RKManagedObjectRequestOperation.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
// limitations under the License.
1919
//
2020

21-
#import <CoreData/CoreData.h>
21+
#ifdef _COREDATADEFINES_H
2222
#import "RKObjectRequestOperation.h"
2323
#import "RKManagedObjectCaching.h"
2424

@@ -140,7 +140,7 @@
140140
141141
@warning A `nil` value for the `managedObjectCache` property is valid, but may result in the creation of duplicate objects.
142142
*/
143-
@property (nonatomic, weak) id<RKManagedObjectCaching> managedObjectCache;
143+
@property (nonatomic, strong) id<RKManagedObjectCaching> managedObjectCache;
144144

145145
/**
146146
An array of `RKFetchRequestBlock` block objects used to map `NSURL` objects into corresponding `NSFetchRequest` objects.
@@ -202,3 +202,5 @@ typedef NSFetchRequest *(^RKFetchRequestBlock)(NSURL *URL);
202202
@return An array of fetch requests from all blocks that match the given URL.
203203
*/
204204
NSArray *RKArrayOfFetchRequestFromBlocksWithURL(NSArray *fetchRequestBlocks, NSURL *URL);
205+
206+
#endif

0 commit comments

Comments
 (0)