Skip to content

Commit

Permalink
Fixed support for iOS prior to iOS 9
Browse files Browse the repository at this point in the history
  • Loading branch information
ipodishima committed Mar 18, 2016
1 parent 4318a70 commit 668e7fe
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 18 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 0.0.5 - Released Mar 17, 2016
Fixed support for iOS 9-

## 0.0.4 - Released Mar 17, 2016
- Added `NSProgress` support
You can track progress using
Expand Down
6 changes: 4 additions & 2 deletions Files/WAMapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ typedef void (^WAMapperCompletionBlock)(NSArray *mappedObjects, NSError *error);

/**
This class will transform a dictionary representation to an object
It supports NSProgress with cancellation (but no pausing). Be aware that according to Apple Documentation about `NSProgressReporting`, "Objects that adopt this protocol should typically be "one-shot""
It supports NSProgress with cancellation (but no pausing). The class mimics `NSProgressReporting` available from iOS 9. Be aware that according to Apple Documentation about `NSProgressReporting`, "Objects that adopt this protocol should typically be "one-shot"". This principle applies here as well.
This means that you should allocate one mapper per mapping execution
*/
@interface WAMapper : NSObject <NSProgressReporting>
@interface WAMapper : NSObject

- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
Expand Down Expand Up @@ -58,4 +58,6 @@ typedef void (^WAMapperCompletionBlock)(NSArray *mappedObjects, NSError *error);

@property (nonatomic, strong, readonly) id <WAStoreProtocol> store;

@property (strong, readonly) NSProgress *progress;

@end
19 changes: 12 additions & 7 deletions Files/WAMapper.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@
@interface WAMapper ()

@property (nonatomic, strong) id <WAStoreProtocol> store;
@property (strong) NSProgress *progress;

@property (nonatomic, strong) NSMutableDictionary *defaultMappingBlocks;

@end

@implementation WAMapper
@synthesize progress = _progress;

- (instancetype)initWithStore:(id<WAStoreProtocol>)store {
WAMProtocolClassAssert(store, WAStoreProtocol);
Expand All @@ -36,7 +37,11 @@ - (instancetype)initWithStore:(id<WAStoreProtocol>)store {
if (self) {
self->_store = store;

self->_progress = [NSProgress progressWithTotalUnitCount:-1];
if ([NSProgress respondsToSelector:NSSelectorFromString(@"discreteProgressWithTotalUnitCount:")]) {
self->_progress = [NSProgress discreteProgressWithTotalUnitCount:-1];
} else {
self->_progress = [NSProgress progressWithTotalUnitCount:-1];
}
self->_progress.cancellable = YES;
self->_progress.pausable = NO;
}
Expand All @@ -53,16 +58,16 @@ - (void)mapFromRepresentation:(id)json mapping:(WAEntityMapping *)mapping comple
WAMAssert(self.store, @"You need to setup a store");
NSArray *objects = [self _arrayFromRepresentation:json mapping:mapping];

self->_progress.totalUnitCount = 2 /* store begin and commit transaction */ + [objects count];
self.progress.totalUnitCount = 2 /* store begin and commit transaction */ + [objects count];

[self.store beginTransaction];
self->_progress.completedUnitCount++;
self.progress.completedUnitCount++;

NSError *error = nil;
NSArray *mappedObjects = [self _mapFromArray:objects mapping:mapping updateProgress:YES error:&error];

[self.store commitTransaction];
self->_progress.completedUnitCount++;
self.progress.completedUnitCount++;

completion(mappedObjects, error);
}
Expand Down Expand Up @@ -151,7 +156,7 @@ - (NSArray *)_mapFromArray:(NSArray *)objectsArray mapping:(WAEntityMapping *)ma
// Go through all objects in json
for (NSDictionary *dic in objectsArray) {
// Get the object if existing
if (self->_progress.isCancelled) {
if (self.progress.isCancelled) {
if (error) {
*error = [NSError errorWithDomain:NSCocoaErrorDomain
code:NSUserCancelledError
Expand Down Expand Up @@ -185,7 +190,7 @@ - (NSArray *)_mapFromArray:(NSArray *)objectsArray mapping:(WAEntityMapping *)ma
[objectsMapped addObjectsFromArray:relationShipObjects];

if (updateProgress) {
self->_progress.completedUnitCount++;
self.progress.completedUnitCount++;
}
}

Expand Down
7 changes: 4 additions & 3 deletions Files/WAReverseMapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ typedef BOOL (^WAReverseMapperShouldMapRelationshipBlock)(NSString *sourceRelati

/**
* This class performs a reverse mapper by turning objects back into dictionaries
* It supports NSProgress with cancellation (but no pausing). Be aware that according to Apple Documentation about `NSProgressReporting`, "Objects that adopt this protocol should typically be "one-shot""
* This means that you should allocate one reversemapper per execution
* It supports NSProgress with cancellation (but no pausing). The class mimics `NSProgressReporting` available from iOS 9. Be aware that according to Apple Documentation about `NSProgressReporting`, "Objects that adopt this protocol should typically be "one-shot"". This principle applies here as well. This means that you should allocate one reversemapper per mapping execution
*/
@interface WAReverseMapper : NSObject <NSProgressReporting>
@interface WAReverseMapper : NSObject

/**
* Turns objects into a dictionary
Expand All @@ -39,4 +38,6 @@ typedef BOOL (^WAReverseMapperShouldMapRelationshipBlock)(NSString *sourceRelati
*/
- (void)addReverseDefaultMappingBlock:(WAMappingBlock)reverseMappingBlock forDestinationClass:(Class)destinationClass;

@property (strong, readonly) NSProgress *progress;

@end
14 changes: 10 additions & 4 deletions Files/WAReverseMapper.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

@interface WAReverseMapper ()

@property (strong) NSProgress *progress;

@property (nonatomic, strong) NSMutableDictionary *defaultReverseMappingBlocks;

@end
Expand All @@ -28,7 +30,11 @@ @implementation WAReverseMapper
- (instancetype)init {
self = [super init];
if (self) {
self->_progress = [NSProgress progressWithTotalUnitCount:-1];
if ([NSProgress respondsToSelector:NSSelectorFromString(@"discreteProgressWithTotalUnitCount:")]) {
self->_progress = [NSProgress discreteProgressWithTotalUnitCount:-1];
} else {
self->_progress = [NSProgress progressWithTotalUnitCount:-1];
}
self->_progress.cancellable = YES;
self->_progress.pausable = NO;
}
Expand All @@ -52,14 +58,14 @@ - (NSArray *)reverseMapObjects:(NSArray *)objects fromMapping:(WAEntityMapping *
return nil;
}

self->_progress.totalUnitCount = [objects count];
self.progress.totalUnitCount = [objects count];

NSMutableArray *allObjectsAsDictionaries = [NSMutableArray array];
// We use this dictionary to avoid infinite loops
NSMutableDictionary *alreadyMappedObjects = [NSMutableDictionary dictionary];

for (id obj in objects) {
if (self->_progress.isCancelled) {
if (self.progress.isCancelled) {
if (error) {
*error = [NSError errorWithDomain:NSCocoaErrorDomain
code:NSUserCancelledError
Expand All @@ -77,7 +83,7 @@ - (NSArray *)reverseMapObjects:(NSArray *)objects fromMapping:(WAEntityMapping *
[allObjectsAsDictionaries addObject:objectAsDictionary];
}

self->_progress.completedUnitCount++;
self.progress.completedUnitCount++;
}

return [allObjectsAsDictionaries copy];
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,10 @@ id(^toDateMappingBlock)(id ) = ^id(id value) {
The same thing happens to the reverse mapper. Note that if you provide a custom mapping on an `NSDate` object for a specific property (like a date with only the year), you can add the property to the entity mapping which will override the default behavior for this specific property.
# Progress and cancellation
Both `WAMapper` and `WAReverseMapper` support `NSProgress` by implementing `NSProgressReporting` protocol. Note that Apple explicitely says `Objects that adopt this protocol should typically be "one-shot"` which means you should use one `WAMapper` per map operation.
Both `WAMapper` and `WAReverseMapper` support `NSProgress`. Note that Apple explicitely says in their documentation about `NSProgressReporting` (which we are mimicing here) `Objects that adopt this protocol should typically be "one-shot"` which means you should use one `WAMapper` per map operation.
## Progress
You can track the progress using this little piece of code. Note that the progress counts the main top objects mapped (if your array contains one object with a thousand objects as relationship, the progress will not reflect the thousand subobjects mapped). This is per `NSProgress` class which supports child progress only from iOS 9.
You can track the progress using this little piece of code. Note that the progress counts the main top objects mapped (if your array contains one object with a thousand objects as relationship, the progress will not reflect the thousand subobjects mapped). This is per choice because adopting child progress prior to iOS 9 is not great.
```objc
[mapper.progress addObserver:self
Expand Down

0 comments on commit 668e7fe

Please sign in to comment.