From d78b9fb0a02c24ae45db1625d29cb5913c2a753b Mon Sep 17 00:00:00 2001 From: Antonio Date: Wed, 22 Jul 2015 12:33:11 +0200 Subject: [PATCH 01/13] Comparable UnixTimestamp attribute to parse object only if the object has changes form the API and if the object has + (NSString *)comparableUnixTimestampAttribute implemented --- .../project.pbxproj | 12 +- .../UserEntity+PDKTModelBuilderEntity.m | 9 +- Demo/PDKTModelBuilder/Models/UserEntity.h | 5 +- Demo/PDKTModelBuilder/Models/UserEntity.m | 5 +- .../PDKTModelBuilder.xcdatamodel/contents | 5 +- .../NSManagedObjectModelsTests.m | 118 ++++++++++++++++++ .../NSManagedObject+PDKTModelBuilder.m | 7 +- PDKTModelBuilder/PDKTEntityDataParser.h | 2 +- PDKTModelBuilder/PDKTEntityDataParser.m | 28 ++++- PDKTModelBuilder/PDKTModelBuilderEntity.h | 1 + 10 files changed, 172 insertions(+), 20 deletions(-) diff --git a/Demo/PDKTModelBuilder.xcodeproj/project.pbxproj b/Demo/PDKTModelBuilder.xcodeproj/project.pbxproj index 180c6a5..ce37b63 100644 --- a/Demo/PDKTModelBuilder.xcodeproj/project.pbxproj +++ b/Demo/PDKTModelBuilder.xcodeproj/project.pbxproj @@ -43,7 +43,6 @@ 883ACAD51A043CCA006139C6 /* NSObjectModelsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 883ACAD41A043CCA006139C6 /* NSObjectModelsTests.m */; }; 88619E271A7FC296009AD2B5 /* PDKTEntityDataParserFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 88619E261A7FC296009AD2B5 /* PDKTEntityDataParserFactory.m */; }; 88619E2A1A7FC2DF009AD2B5 /* PDKTCoreDataEntityDataParserFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 88619E291A7FC2DF009AD2B5 /* PDKTCoreDataEntityDataParserFactory.m */; }; - 88619E2D1A7FC551009AD2B5 /* UserEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = 88619E2C1A7FC551009AD2B5 /* UserEntity.m */; }; 88C464511A1291D000A6B9D6 /* NSManagedObjectModelsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C464501A1291D000A6B9D6 /* NSManagedObjectModelsTests.m */; }; 88C4645C1A1292BE00A6B9D6 /* UserEntity+PDKTModelBuilderEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C4645B1A1292BE00A6B9D6 /* UserEntity+PDKTModelBuilderEntity.m */; }; 88C4645F1A1292D100A6B9D6 /* PictureEntity+PDKTModelBuilderEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C4645E1A1292D100A6B9D6 /* PictureEntity+PDKTModelBuilderEntity.m */; }; @@ -52,6 +51,7 @@ 88C4646E1A12938200A6B9D6 /* TestablePicture.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C4646A1A12938200A6B9D6 /* TestablePicture.m */; }; 88C4646F1A12948300A6B9D6 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 88C464641A12938200A6B9D6 /* Info.plist */; }; 88C464751A129FAD00A6B9D6 /* PictureEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C464741A129FAD00A6B9D6 /* PictureEntity.m */; }; + A9D84FB31B5FA4DE003E3BD1 /* UserEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = A9D84FB21B5FA4DE003E3BD1 /* UserEntity.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -131,8 +131,6 @@ 88619E261A7FC296009AD2B5 /* PDKTEntityDataParserFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDKTEntityDataParserFactory.m; sourceTree = ""; }; 88619E281A7FC2DF009AD2B5 /* PDKTCoreDataEntityDataParserFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDKTCoreDataEntityDataParserFactory.h; sourceTree = ""; }; 88619E291A7FC2DF009AD2B5 /* PDKTCoreDataEntityDataParserFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDKTCoreDataEntityDataParserFactory.m; sourceTree = ""; }; - 88619E2B1A7FC551009AD2B5 /* UserEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserEntity.h; sourceTree = ""; }; - 88619E2C1A7FC551009AD2B5 /* UserEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UserEntity.m; sourceTree = ""; }; 88C464501A1291D000A6B9D6 /* NSManagedObjectModelsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSManagedObjectModelsTests.m; sourceTree = ""; }; 88C4645A1A1292BE00A6B9D6 /* UserEntity+PDKTModelBuilderEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UserEntity+PDKTModelBuilderEntity.h"; sourceTree = ""; }; 88C4645B1A1292BE00A6B9D6 /* UserEntity+PDKTModelBuilderEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UserEntity+PDKTModelBuilderEntity.m"; sourceTree = ""; }; @@ -147,6 +145,8 @@ 88C4646A1A12938200A6B9D6 /* TestablePicture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestablePicture.m; sourceTree = ""; }; 88C464731A129FAD00A6B9D6 /* PictureEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PictureEntity.h; sourceTree = ""; }; 88C464741A129FAD00A6B9D6 /* PictureEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PictureEntity.m; sourceTree = ""; }; + A9D84FB11B5FA4DE003E3BD1 /* UserEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserEntity.h; sourceTree = ""; }; + A9D84FB21B5FA4DE003E3BD1 /* UserEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UserEntity.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -350,8 +350,8 @@ 88C464521A12927100A6B9D6 /* Models */ = { isa = PBXGroup; children = ( - 88619E2B1A7FC551009AD2B5 /* UserEntity.h */, - 88619E2C1A7FC551009AD2B5 /* UserEntity.m */, + A9D84FB11B5FA4DE003E3BD1 /* UserEntity.h */, + A9D84FB21B5FA4DE003E3BD1 /* UserEntity.m */, 88C464731A129FAD00A6B9D6 /* PictureEntity.h */, 88C464741A129FAD00A6B9D6 /* PictureEntity.m */, 88C464591A1292A800A6B9D6 /* PDKTModelBuilderEntity */, @@ -494,7 +494,7 @@ 88619E2A1A7FC2DF009AD2B5 /* PDKTCoreDataEntityDataParserFactory.m in Sources */, 883ACAD01A043815006139C6 /* PDKTURLTransformer.m in Sources */, 883ACA6A1A0417BA006139C6 /* PDKTCoreDataEntityRelationship.m in Sources */, - 88619E2D1A7FC551009AD2B5 /* UserEntity.m in Sources */, + A9D84FB31B5FA4DE003E3BD1 /* UserEntity.m in Sources */, 883ACACE1A043815006139C6 /* PDKTIntegerTransformer.m in Sources */, 883ACA141A041786006139C6 /* AppDelegate.m in Sources */, 88C464751A129FAD00A6B9D6 /* PictureEntity.m in Sources */, diff --git a/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/UserEntity+PDKTModelBuilderEntity.m b/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/UserEntity+PDKTModelBuilderEntity.m index 015ebc2..4509d2a 100644 --- a/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/UserEntity+PDKTModelBuilderEntity.m +++ b/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/UserEntity+PDKTModelBuilderEntity.m @@ -16,12 +16,14 @@ + (NSDictionary *)propertiesBindings{ @"userId":@"id", @"userName":@"name", @"userEmail":@"email", - @"userBlogURL":@"blog_url" + @"userBlogURL":@"blog_url", + @"entityUpdateUnixTimestamp": @"updated_at" }; } + (NSDictionary *)propertiesTypeTransformers{ return @{ - @"userBlogURL":[PDKTURLTransformer new] + @"userBlogURL":[PDKTURLTransformer new], + @"entityUpdateUnixTimestamp": [PDKTIntegerTransformer new] }; } + (NSDictionary *)relationshipsBindings{ @@ -29,6 +31,9 @@ + (NSDictionary *)relationshipsBindings{ @"hasPictures":[PDKTCoreDataEntityRelationship oneToManyRelationshipForKeyPath:@"pictures" andClass:[PictureEntity class]] }; } ++ (NSString *)comparableUnixTimestampAttribute { + return @"entityUpdateUnixTimestamp"; +} + (NSDictionary *)customDataDictionaryWithSourceDataDictionary:(NSDictionary *)dictionary{ NSMutableDictionary *dataDictionary = [dictionary mutableCopy]; diff --git a/Demo/PDKTModelBuilder/Models/UserEntity.h b/Demo/PDKTModelBuilder/Models/UserEntity.h index 48d7bcd..9ab7c59 100644 --- a/Demo/PDKTModelBuilder/Models/UserEntity.h +++ b/Demo/PDKTModelBuilder/Models/UserEntity.h @@ -2,7 +2,7 @@ // UserEntity.h // PDKTModelBuilder // -// Created by Daniel García on 02/02/15. +// Created by Antonio on 22/7/15. // Copyright (c) 2015 Produkt. All rights reserved. // @@ -13,11 +13,12 @@ @interface UserEntity : NSManagedObject +@property (nonatomic, retain) NSDate * entityUpdateDate; @property (nonatomic, retain) id userBlogURL; @property (nonatomic, retain) NSString * userEmail; @property (nonatomic, retain) NSString * userId; @property (nonatomic, retain) NSString * userName; -@property (nonatomic, retain) NSDate * entityUpdateDate; +@property (nonatomic, retain) NSNumber * entityUpdateUnixTimestamp; @property (nonatomic, retain) NSSet *hasPictures; @end diff --git a/Demo/PDKTModelBuilder/Models/UserEntity.m b/Demo/PDKTModelBuilder/Models/UserEntity.m index 8e04d99..22e497d 100644 --- a/Demo/PDKTModelBuilder/Models/UserEntity.m +++ b/Demo/PDKTModelBuilder/Models/UserEntity.m @@ -2,7 +2,7 @@ // UserEntity.m // PDKTModelBuilder // -// Created by Daniel García on 02/02/15. +// Created by Antonio on 22/7/15. // Copyright (c) 2015 Produkt. All rights reserved. // @@ -12,11 +12,12 @@ @implementation UserEntity +@dynamic entityUpdateDate; @dynamic userBlogURL; @dynamic userEmail; @dynamic userId; @dynamic userName; -@dynamic entityUpdateDate; +@dynamic entityUpdateUnixTimestamp; @dynamic hasPictures; @end diff --git a/Demo/PDKTModelBuilder/PDKTModelBuilder.xcdatamodeld/PDKTModelBuilder.xcdatamodel/contents b/Demo/PDKTModelBuilder/PDKTModelBuilder.xcdatamodeld/PDKTModelBuilder.xcdatamodel/contents index ffa9527..ea29238 100644 --- a/Demo/PDKTModelBuilder/PDKTModelBuilder.xcdatamodeld/PDKTModelBuilder.xcdatamodel/contents +++ b/Demo/PDKTModelBuilder/PDKTModelBuilder.xcdatamodeld/PDKTModelBuilder.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -8,6 +8,7 @@ + @@ -16,6 +17,6 @@ - + \ No newline at end of file diff --git a/Demo/PDKTModelBuilderTests/NSManagedObjectModelsTests.m b/Demo/PDKTModelBuilderTests/NSManagedObjectModelsTests.m index 0f43cd9..583cef6 100644 --- a/Demo/PDKTModelBuilderTests/NSManagedObjectModelsTests.m +++ b/Demo/PDKTModelBuilderTests/NSManagedObjectModelsTests.m @@ -147,4 +147,122 @@ - (void)testAPIResponseHotFix { } } +- (void)testEqualComparableAttributes { + NSDictionary *userDictionary = @{ + @"id":@"1", + @"name":@"John Doe", + @"email":@"john.doe@apple.com", + @"blog_url":@"www.tumblr.com/johndoe", + @"updated_at": @1437216918 + }; + + UserEntity *user = [UserEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:userDictionary]; + XCTAssertEqualObjects(user.userId, @"1"); + XCTAssertEqualObjects(user.userName, @"John Doe"); + XCTAssertEqualObjects(user.userEmail, @"john.doe@apple.com"); + XCTAssertEqualObjects(user.userBlogURL, [NSURL URLWithString:@"www.tumblr.com/johndoe"]); + + NSDate *dateSaved = user.entityUpdateDate; + + UserEntity *userUpdated = [UserEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:userDictionary]; + XCTAssertEqualObjects(userUpdated.userId, @"1"); + XCTAssertEqualObjects(userUpdated.userName, @"John Doe"); + XCTAssertEqualObjects(userUpdated.userEmail, @"john.doe@apple.com"); + XCTAssertEqualObjects(userUpdated.userBlogURL, [NSURL URLWithString:@"www.tumblr.com/johndoe"]); + XCTAssertEqualObjects(userUpdated.entityUpdateDate, dateSaved); +} + +- (void)testNotEqualComparableAttributes { + NSDictionary *userDictionary = @{ + @"id":@"1", + @"name":@"John Doe", + @"email":@"john.doe@apple.com", + @"blog_url":@"www.tumblr.com/johndoe", + @"updated_at": @1437216918 + }; + + UserEntity *user = [UserEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:userDictionary]; + XCTAssertEqualObjects(user.userId, @"1"); + XCTAssertEqualObjects(user.userName, @"John Doe"); + XCTAssertEqualObjects(user.userEmail, @"john.doe@apple.com"); + XCTAssertEqualObjects(user.userBlogURL, [NSURL URLWithString:@"www.tumblr.com/johndoe"]); + + NSDate *dateSaved = user.entityUpdateDate; + + NSDictionary *userDictionaryUpdated = @{ + @"id":@"1", + @"name":@"John Doe Updated", + @"email":@"john.doe@apple.com", + @"blog_url":@"www.tumblr.com/johndoe", + @"updated_at": @1437216919 + }; + + UserEntity *userUpdated = [UserEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:userDictionaryUpdated]; + XCTAssertEqualObjects(userUpdated.userId, @"1"); + XCTAssertEqualObjects(userUpdated.userName, @"John Doe Updated"); + XCTAssertEqualObjects(userUpdated.userEmail, @"john.doe@apple.com"); + XCTAssertEqualObjects(userUpdated.userBlogURL, [NSURL URLWithString:@"www.tumblr.com/johndoe"]); + XCTAssertNotEqualObjects(userUpdated.entityUpdateDate, dateSaved); +} +- (void)testNSManagedObjectsRelationshipsUpdated { + NSDictionary *userDictionary = @{ + @"id":@"1", + @"name":@"John Doe", + @"email":@"john.doe@apple.com", + @"blog_url":@"www.tumblr.com/johndoe", + @"updated_at": @1437216918, + @"pictures":@[ + @{ + @"id":@"1", + @"url":@"www.apple.com/images/picture.jpg", + @"published_on":@"1415735002" + }, + @{ + @"id":@"2", + @"url":@"www.apple.com/images/picture2.jpg", + @"published_on":@"1415735002" + } + ] + }; + + UserEntity *user = [UserEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:userDictionary]; + XCTAssertNotNil(user.hasPictures); + XCTAssertNotEqual(user.hasPictures.count, 0); + for (PictureEntity *picture in user.hasPictures) { + XCTAssert([picture isKindOfClass:[PictureEntity class]]); + + // Check inverse relationship + XCTAssertEqualObjects(picture.author, user); + } + + NSDictionary *userUpdateRelationshipDictionary = @{ + @"id":@"1", + @"name":@"John Doe", + @"email":@"john.doe@apple.com", + @"blog_url":@"www.tumblr.com/johndoe", + @"updated_at": @1437216918, + @"pictures":@[ + @{ + @"id":@"1", + @"url":@"www.apple.com/images/picture_updated.jpg", + @"published_on":@"1415735002" + }, + @{ + @"id":@"2", + @"url":@"www.apple.com/images/picture2.jpg", + @"published_on":@"1415735002" + } + ] + }; + + UserEntity *userUpdateRelations = [UserEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:userUpdateRelationshipDictionary]; + XCTAssertNotNil(userUpdateRelations); + for (PictureEntity *picture in userUpdateRelations.hasPictures) { + if ([picture.pictureId isEqualToString:@"1"]) { + XCTAssertEqualObjects(picture.pictureURL, [NSURL URLWithString:@"www.apple.com/images/picture_updated.jpg"]); + } + } + +} + @end diff --git a/PDKTModelBuilder/CoreData/NSManagedObject+PDKTModelBuilder.m b/PDKTModelBuilder/CoreData/NSManagedObject+PDKTModelBuilder.m index 153aada..231fd07 100644 --- a/PDKTModelBuilder/CoreData/NSManagedObject+PDKTModelBuilder.m +++ b/PDKTModelBuilder/CoreData/NSManagedObject+PDKTModelBuilder.m @@ -49,9 +49,10 @@ + (instancetype)updateOrInsertIntoManagedObjectContext:(NSManagedObjectContext * entity = [NSEntityDescription insertNewObjectForEntityForName:[NSString stringWithFormat:@"%@",entityName] inManagedObjectContext:managedObjectContext]; } PDKTEntityDataParser *entityDataParser = [PDKTCoreDataEntityDataParserFactory dataParserForCoreDataEntityWithDictionary:dictionary andEntity:entity]; - [entityDataParser executeDataParsing]; - if ([entity conformsToProtocol:@protocol(PDKTModelBuilderCoreDataEntity)] && [entity respondsToSelector:@selector(setEntityUpdateDate:)]) { - [(NSManagedObject *)entity setEntityUpdateDate:[NSDate date]]; + if ([entityDataParser executeDataParsing]) { + if ([entity conformsToProtocol:@protocol(PDKTModelBuilderCoreDataEntity)] && [entity respondsToSelector:@selector(setEntityUpdateDate:)]) { + [(NSManagedObject *)entity setEntityUpdateDate:[NSDate date]]; + } } return entity; } diff --git a/PDKTModelBuilder/PDKTEntityDataParser.h b/PDKTModelBuilder/PDKTEntityDataParser.h index 67bbe02..46f8ebb 100644 --- a/PDKTModelBuilder/PDKTEntityDataParser.h +++ b/PDKTModelBuilder/PDKTEntityDataParser.h @@ -11,7 +11,7 @@ @interface PDKTEntityDataParser : NSObject - (instancetype)initWithDictionary:(NSDictionary *)dictionary andEntity:(NSObject *)entity; -- (void)executeDataParsing; +- (BOOL)executeDataParsing; @end @interface PDKTEntityDataParser(PropertyParse) diff --git a/PDKTModelBuilder/PDKTEntityDataParser.m b/PDKTModelBuilder/PDKTEntityDataParser.m index 84c75b2..5e13773 100644 --- a/PDKTModelBuilder/PDKTEntityDataParser.m +++ b/PDKTModelBuilder/PDKTEntityDataParser.m @@ -34,9 +34,14 @@ - (NSDictionary *)sourceDictionaryWithDictionary:(NSDictionary *)dictionary forE } return sourceDictionary; } -- (void)executeDataParsing{ - [self parseDictionary:self.dictionary withEntity:self.entity]; +- (BOOL)executeDataParsing{ + BOOL isExecuteEntityParsing = NO; + if ([self entity:self.entity needsParsingWithDictionary:self.dictionary]) { + [self parseDictionary:self.dictionary withEntity:self.entity]; + isExecuteEntityParsing = YES; + } [self parseRelationshipsInDictionary:self.dictionary withEntity:self.entity]; + return isExecuteEntityParsing; } #pragma mark - Automated properties parsing - (void)parseDictionary:(NSDictionary *)dictionary withEntity:(NSObject *)entity{ @@ -52,6 +57,25 @@ - (void)parseDictionary:(NSDictionary *)dictionary withEntity:(NSObject *)entity{ } + +#pragma mark - Private Methods +- (BOOL)entity:(NSObject *)entity needsParsingWithDictionary:(NSDictionary *)dictionary { + BOOL entityNeedsParsing = YES; + NSString *attributeName; + if ([[entity class] respondsToSelector:@selector(comparableUnixTimestampAttribute)]) { + attributeName = [[entity class] comparableUnixTimestampAttribute]; + } + if (attributeName) { + NSNumber *apiAttributeValue = [[self class] propertyValueForKey:attributeName inDictionary:dictionary forEntityClass:[entity class]]; + if (apiAttributeValue) { + NSNumber *entityComparableAttribute = [entity valueForKey:attributeName]; + if (entityComparableAttribute && ([apiAttributeValue compare:entityComparableAttribute] == NSOrderedSame)) { + entityNeedsParsing = NO; + } + } + } + return entityNeedsParsing; +} @end diff --git a/PDKTModelBuilder/PDKTModelBuilderEntity.h b/PDKTModelBuilder/PDKTModelBuilderEntity.h index 11f10a0..29cba86 100644 --- a/PDKTModelBuilder/PDKTModelBuilderEntity.h +++ b/PDKTModelBuilder/PDKTModelBuilderEntity.h @@ -14,4 +14,5 @@ + (NSDictionary *)relationshipsBindings; + (NSDictionary *)propertiesTypeTransformers; + (NSDictionary *)customDataDictionaryWithSourceDataDictionary:(NSDictionary *)dictionary; ++ (NSString *)comparableUnixTimestampAttribute; @end From 279847bef83c71e46516f0c32592e61af8564386 Mon Sep 17 00:00:00 2001 From: Antonio Date: Mon, 21 Sep 2015 12:03:26 +0200 Subject: [PATCH 02/13] Entity Name as a required method to avoid namespaces Swift --- .../PictureEntity+PDKTModelBuilderEntity.m | 6 ++++++ .../UserEntity+PDKTModelBuilderEntity.m | 6 ++++++ .../CoreData/NSManagedObject+PDKTModelBuilder.h | 2 ++ .../CoreData/NSManagedObject+PDKTModelBuilder.m | 11 ++++++----- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/PictureEntity+PDKTModelBuilderEntity.m b/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/PictureEntity+PDKTModelBuilderEntity.m index 3e30d5b..3c15c04 100644 --- a/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/PictureEntity+PDKTModelBuilderEntity.m +++ b/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/PictureEntity+PDKTModelBuilderEntity.m @@ -10,6 +10,9 @@ #import "PDKTDataTransformers.h" @implementation PictureEntity (PDKTModelBuilderEntity) ++ (NSString *)entityName { + return @"PictureEntity"; +} + (NSDictionary *)propertiesBindings{ return @{ @"pictureId":@"id", @@ -23,4 +26,7 @@ + (NSDictionary *)propertiesTypeTransformers{ @"pictureURL":[PDKTURLTransformer new] }; } ++ (NSString *)entityIdPropertyName { + return @"pictureId"; +} @end diff --git a/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/UserEntity+PDKTModelBuilderEntity.m b/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/UserEntity+PDKTModelBuilderEntity.m index 4509d2a..5b08b34 100644 --- a/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/UserEntity+PDKTModelBuilderEntity.m +++ b/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/UserEntity+PDKTModelBuilderEntity.m @@ -11,6 +11,9 @@ #import "PictureEntity.h" @implementation UserEntity (PDKTModelBuilderEntity) ++ (NSString *)entityName { + return @"UserEntity"; +} + (NSDictionary *)propertiesBindings{ return @{ @"userId":@"id", @@ -26,6 +29,9 @@ + (NSDictionary *)propertiesTypeTransformers{ @"entityUpdateUnixTimestamp": [PDKTIntegerTransformer new] }; } ++ (NSString *)entityIdPropertyName { + return @"userId"; +} + (NSDictionary *)relationshipsBindings{ return @{ @"hasPictures":[PDKTCoreDataEntityRelationship oneToManyRelationshipForKeyPath:@"pictures" andClass:[PictureEntity class]] diff --git a/PDKTModelBuilder/CoreData/NSManagedObject+PDKTModelBuilder.h b/PDKTModelBuilder/CoreData/NSManagedObject+PDKTModelBuilder.h index 47d1042..c03c238 100644 --- a/PDKTModelBuilder/CoreData/NSManagedObject+PDKTModelBuilder.h +++ b/PDKTModelBuilder/CoreData/NSManagedObject+PDKTModelBuilder.h @@ -12,6 +12,8 @@ @protocol PDKTModelBuilderCoreDataEntity @optional @property (strong,nonatomic) NSDate *entityUpdateDate; +@required ++ (NSString *)entityName; + (NSString *)entityIdPropertyName; @end diff --git a/PDKTModelBuilder/CoreData/NSManagedObject+PDKTModelBuilder.m b/PDKTModelBuilder/CoreData/NSManagedObject+PDKTModelBuilder.m index 231fd07..67bfd77 100644 --- a/PDKTModelBuilder/CoreData/NSManagedObject+PDKTModelBuilder.m +++ b/PDKTModelBuilder/CoreData/NSManagedObject+PDKTModelBuilder.m @@ -12,7 +12,7 @@ @implementation NSManagedObject (PDKTModelBuilderEntityDefault) + (NSString *)defaultEntityIdPropertyName{ - return [self defaultEntityIdPropertyNameForEntityName:NSStringFromClass([self class])]; + return [self defaultEntityIdPropertyNameForEntityName:[(id)self entityName]]; } + (NSString *)defaultEntityIdPropertyNameForEntityName:(NSString *)entityName{ return [[NSString stringWithFormat:@"%@Id",[entityName stringByReplacingOccurrencesOfString:@"Entity" withString:@""]]stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:[[entityName substringToIndex:1]lowercaseString]]; @@ -27,7 +27,7 @@ + (void)validateDefaultObjectId:(NSString *)objectId{ @implementation NSManagedObject (PDKTModelBuilder) + (instancetype)updateOrInsertIntoManagedObjectContext:(NSManagedObjectContext *)managedObjectContext withDictionary:(NSDictionary *)dictionary{ NSAssert([[self class] conformsToProtocol:@protocol(PDKTModelBuilderCoreDataEntity)], @"must implement PDKTModelBuilderCoreDataEntity for using this method"); - NSString *entityName=NSStringFromClass([self class]); + NSString *entityName = [(id)self entityName]; NSString *objectId = [self entityId]; NSString *objectIdValue=[PDKTEntityDataParser propertyValueForKey:objectId inDictionary:dictionary forEntityClass:[self class]]; if (!objectIdValue) { @@ -58,7 +58,7 @@ + (instancetype)updateOrInsertIntoManagedObjectContext:(NSManagedObjectContext * } + (instancetype)insertIntoManagedObjectContext:(NSManagedObjectContext *)managedObjectContext withDictionary:(NSDictionary *)dictionary{ NSAssert([[self class] conformsToProtocol:@protocol(PDKTModelBuilderCoreDataEntity)], @"must implement PDKTModelBuilderCoreDataEntity for using this method"); - NSString *entityName=NSStringFromClass([self class]); + NSString *entityName = [(id)self entityName]; NSString *objectIdValue=[self objectIdWithDictionary:dictionary]; if (!objectIdValue) { return nil; @@ -74,7 +74,7 @@ + (NSString *)objectIdWithDictionary:(NSDictionary *)dictionary{ return objectIdValue; } + (instancetype)fetchObjectWithValue:(id)value forKey:(NSString *)key inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext{ - NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([self class])]; + NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[(id)self entityName]]; fetchRequest.predicate = [NSPredicate predicateWithFormat:@"%@ = %K",value,key]; fetchRequest.fetchLimit = 1; NSError *error=nil; @@ -86,7 +86,7 @@ + (instancetype)fetchObjectWithValue:(id)value forKey:(NSString *)key inManagedO return fetchedObject; } + (NSString *)entityId{ - NSString *entityName=NSStringFromClass([self class]); + NSString *entityName = [(id)self entityName]; NSString *objectId; if ([self respondsToSelector:@selector(entityIdPropertyName)]) { objectId = [(id)self entityIdPropertyName]; @@ -96,5 +96,6 @@ + (NSString *)entityId{ } return objectId.length ? objectId : nil; } + @end From f1575c38f60c38572ce602273570b77843e48610 Mon Sep 17 00:00:00 2001 From: Antonio Date: Wed, 14 Oct 2015 11:54:13 +0200 Subject: [PATCH 03/13] Comparable attribute value as an "id". Change protocol method "comparableUnixTimestampAttribute" for "comparableAttribute" --- .../UserEntity+PDKTModelBuilderEntity.m | 2 +- PDKTModelBuilder/PDKTEntityDataParser.m | 14 ++++++++------ PDKTModelBuilder/PDKTModelBuilderEntity.h | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/UserEntity+PDKTModelBuilderEntity.m b/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/UserEntity+PDKTModelBuilderEntity.m index 5b08b34..b8dcb2b 100644 --- a/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/UserEntity+PDKTModelBuilderEntity.m +++ b/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/UserEntity+PDKTModelBuilderEntity.m @@ -37,7 +37,7 @@ + (NSDictionary *)relationshipsBindings{ @"hasPictures":[PDKTCoreDataEntityRelationship oneToManyRelationshipForKeyPath:@"pictures" andClass:[PictureEntity class]] }; } -+ (NSString *)comparableUnixTimestampAttribute { ++ (NSString *)comparableAttribute { return @"entityUpdateUnixTimestamp"; } + (NSDictionary *)customDataDictionaryWithSourceDataDictionary:(NSDictionary *)dictionary{ diff --git a/PDKTModelBuilder/PDKTEntityDataParser.m b/PDKTModelBuilder/PDKTEntityDataParser.m index 5e13773..4d2b1d2 100644 --- a/PDKTModelBuilder/PDKTEntityDataParser.m +++ b/PDKTModelBuilder/PDKTEntityDataParser.m @@ -62,15 +62,17 @@ - (void)parseRelationshipsInDictionary:(NSDictionary *)dictionary withEntity:(NS - (BOOL)entity:(NSObject *)entity needsParsingWithDictionary:(NSDictionary *)dictionary { BOOL entityNeedsParsing = YES; NSString *attributeName; - if ([[entity class] respondsToSelector:@selector(comparableUnixTimestampAttribute)]) { - attributeName = [[entity class] comparableUnixTimestampAttribute]; + if ([[entity class] respondsToSelector:@selector(comparableAttribute)]) { + attributeName = [[entity class] comparableAttribute]; } if (attributeName) { - NSNumber *apiAttributeValue = [[self class] propertyValueForKey:attributeName inDictionary:dictionary forEntityClass:[entity class]]; + id apiAttributeValue = [[self class] propertyValueForKey:attributeName inDictionary:dictionary forEntityClass:[entity class]]; if (apiAttributeValue) { - NSNumber *entityComparableAttribute = [entity valueForKey:attributeName]; - if (entityComparableAttribute && ([apiAttributeValue compare:entityComparableAttribute] == NSOrderedSame)) { - entityNeedsParsing = NO; + id entityComparableAttribute = [entity valueForKey:attributeName]; + if ([apiAttributeValue respondsToSelector:@selector(compare:)] && [entityComparableAttribute respondsToSelector:@selector(compare:)]) { + if (entityComparableAttribute && ([apiAttributeValue compare:entityComparableAttribute] == NSOrderedSame)) { + entityNeedsParsing = NO; + } } } } diff --git a/PDKTModelBuilder/PDKTModelBuilderEntity.h b/PDKTModelBuilder/PDKTModelBuilderEntity.h index 29cba86..8d67044 100644 --- a/PDKTModelBuilder/PDKTModelBuilderEntity.h +++ b/PDKTModelBuilder/PDKTModelBuilderEntity.h @@ -14,5 +14,5 @@ + (NSDictionary *)relationshipsBindings; + (NSDictionary *)propertiesTypeTransformers; + (NSDictionary *)customDataDictionaryWithSourceDataDictionary:(NSDictionary *)dictionary; -+ (NSString *)comparableUnixTimestampAttribute; ++ (NSString *)comparableAttribute; @end From adf44bf4dbfc0d1ba53b8c3923667585ac4c935f Mon Sep 17 00:00:00 2001 From: Antonio Date: Wed, 14 Oct 2015 12:04:00 +0200 Subject: [PATCH 04/13] Remove check for "entityComparableAttribute", because if it doesn't exist, [entityComparableAttribute respondsToSelector:@selector(compare:)] return NO --- PDKTModelBuilder/PDKTEntityDataParser.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PDKTModelBuilder/PDKTEntityDataParser.m b/PDKTModelBuilder/PDKTEntityDataParser.m index 4d2b1d2..d49eb27 100644 --- a/PDKTModelBuilder/PDKTEntityDataParser.m +++ b/PDKTModelBuilder/PDKTEntityDataParser.m @@ -70,7 +70,7 @@ - (BOOL)entity:(NSObject *)entity needsParsingWithDictio if (apiAttributeValue) { id entityComparableAttribute = [entity valueForKey:attributeName]; if ([apiAttributeValue respondsToSelector:@selector(compare:)] && [entityComparableAttribute respondsToSelector:@selector(compare:)]) { - if (entityComparableAttribute && ([apiAttributeValue compare:entityComparableAttribute] == NSOrderedSame)) { + if ([apiAttributeValue compare:entityComparableAttribute] == NSOrderedSame) { entityNeedsParsing = NO; } } From 9e1f73395e4c8f78a8ddb431445d51e64f618fc3 Mon Sep 17 00:00:00 2001 From: Antonio Date: Thu, 12 Nov 2015 15:05:40 +0100 Subject: [PATCH 05/13] Add + (NSString *)entityName; and + (NSString *)entityIdPropertyName; to PDKTModelBuilderEntity --- Demo/PDKTModelBuilderTests/NSObjectModelsTests.m | 2 ++ .../TestablePicture+PDKTModelBuilderEntity.m | 6 ++++++ .../CoreData/NSManagedObject+PDKTModelBuilder.h | 3 --- PDKTModelBuilder/PDKTModelBuilderEntity.h | 2 ++ 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Demo/PDKTModelBuilderTests/NSObjectModelsTests.m b/Demo/PDKTModelBuilderTests/NSObjectModelsTests.m index a6d507d..970a49f 100644 --- a/Demo/PDKTModelBuilderTests/NSObjectModelsTests.m +++ b/Demo/PDKTModelBuilderTests/NSObjectModelsTests.m @@ -41,6 +41,8 @@ - (void)testObjectAutocreation { XCTAssertEqualObjects(picture.pictureURL, [NSURL URLWithString:@"http://www.apple.com"]); XCTAssertEqualObjects(picture.pictureRating, @(3.5)); XCTAssertEqualObjects(picture.picturePublishedDate, [NSDate dateWithTimeIntervalSince1970:1414784879]); + XCTAssertEqual([TestablePicture entityName], @"TestablePicture"); + XCTAssertEqual([TestablePicture entityIdPropertyName], @"pictureId"); } - (void)testIncompleteObjectAutocreation{ diff --git a/Demo/PDKTModelBuilderTests/Supporting Files/TestablePicture+PDKTModelBuilderEntity.m b/Demo/PDKTModelBuilderTests/Supporting Files/TestablePicture+PDKTModelBuilderEntity.m index 5b618b5..a55d143 100644 --- a/Demo/PDKTModelBuilderTests/Supporting Files/TestablePicture+PDKTModelBuilderEntity.m +++ b/Demo/PDKTModelBuilderTests/Supporting Files/TestablePicture+PDKTModelBuilderEntity.m @@ -25,4 +25,10 @@ + (NSDictionary *)propertiesTypeTransformers{ @"picturePublishedDate":[PDKTDateTransformer new] }; } ++ (NSString *)entityName { + return @"TestablePicture"; +} ++ (NSString *)entityIdPropertyName { + return @"pictureId"; +} @end diff --git a/PDKTModelBuilder/CoreData/NSManagedObject+PDKTModelBuilder.h b/PDKTModelBuilder/CoreData/NSManagedObject+PDKTModelBuilder.h index c03c238..ea059c7 100644 --- a/PDKTModelBuilder/CoreData/NSManagedObject+PDKTModelBuilder.h +++ b/PDKTModelBuilder/CoreData/NSManagedObject+PDKTModelBuilder.h @@ -12,9 +12,6 @@ @protocol PDKTModelBuilderCoreDataEntity @optional @property (strong,nonatomic) NSDate *entityUpdateDate; -@required -+ (NSString *)entityName; -+ (NSString *)entityIdPropertyName; @end @class PDKTEntityDataParser; diff --git a/PDKTModelBuilder/PDKTModelBuilderEntity.h b/PDKTModelBuilder/PDKTModelBuilderEntity.h index 8d67044..da5f929 100644 --- a/PDKTModelBuilder/PDKTModelBuilderEntity.h +++ b/PDKTModelBuilder/PDKTModelBuilderEntity.h @@ -10,6 +10,8 @@ @protocol PDKTModelBuilderEntity + (NSDictionary *)propertiesBindings; ++ (NSString *)entityName; ++ (NSString *)entityIdPropertyName; @optional + (NSDictionary *)relationshipsBindings; + (NSDictionary *)propertiesTypeTransformers; From 22d74394601af604dae75e72ff49fb646dad43fc Mon Sep 17 00:00:00 2001 From: Antonio Date: Mon, 30 Nov 2015 12:19:38 +0100 Subject: [PATCH 06/13] Update relation ships (OnteToMany and OneToOne) if the data in the server is different from local. See 3 last tests in NSManagedObjectModelsTests to understand this fix --- .../PictureEntity+PDKTModelBuilderEntity.m | 15 +- Demo/PDKTModelBuilder/Models/PictureEntity.h | 1 + Demo/PDKTModelBuilder/Models/PictureEntity.m | 1 + .../PDKTModelBuilder.xcdatamodel/contents | 5 +- .../NSManagedObjectModelsTests.m | 147 ++++++++++++++++-- ..._PDKTCoreDataEntityRelationshipOneToMany.m | 14 +- ...__PDKTCoreDataEntityRelationshipOneToOne.m | 2 + 7 files changed, 164 insertions(+), 21 deletions(-) diff --git a/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/PictureEntity+PDKTModelBuilderEntity.m b/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/PictureEntity+PDKTModelBuilderEntity.m index 3c15c04..96fb5ac 100644 --- a/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/PictureEntity+PDKTModelBuilderEntity.m +++ b/Demo/PDKTModelBuilder/Models/PDKTModelBuilderEntity/PictureEntity+PDKTModelBuilderEntity.m @@ -8,6 +8,7 @@ #import "PictureEntity+PDKTModelBuilderEntity.h" #import "PDKTDataTransformers.h" +#import "UserEntity.h" @implementation PictureEntity (PDKTModelBuilderEntity) + (NSString *)entityName { @@ -17,16 +18,26 @@ + (NSDictionary *)propertiesBindings{ return @{ @"pictureId":@"id", @"picturePublishedDate":@"published_on", - @"pictureURL":@"url" + @"pictureURL":@"url", + @"pictureModificationDateUnixTimestamp": @"updated_at" }; } + (NSDictionary *)propertiesTypeTransformers{ return @{ @"picturePublishedDate":[PDKTDateTransformer new], - @"pictureURL":[PDKTURLTransformer new] + @"pictureURL":[PDKTURLTransformer new], + @"pictureModificationDateUnixTimestamp": [PDKTIntegerTransformer new] }; } + (NSString *)entityIdPropertyName { return @"pictureId"; } ++ (NSDictionary *)relationshipsBindings{ + return @{ + @"author": [PDKTCoreDataEntityRelationship oneToOneRelationshipForKeyPath:@"author" andClass:[UserEntity class]] + }; +} ++ (NSString *)comparableAttribute { + return @"pictureModificationDateUnixTimestamp"; +} @end diff --git a/Demo/PDKTModelBuilder/Models/PictureEntity.h b/Demo/PDKTModelBuilder/Models/PictureEntity.h index 2e30cd8..34790e5 100644 --- a/Demo/PDKTModelBuilder/Models/PictureEntity.h +++ b/Demo/PDKTModelBuilder/Models/PictureEntity.h @@ -17,5 +17,6 @@ @property (nonatomic, retain) NSDate * picturePublishedDate; @property (nonatomic, retain) id pictureURL; @property (nonatomic, retain) UserEntity *author; +@property (nonatomic, retain) NSNumber * pictureModificationDateUnixTimestamp; @end diff --git a/Demo/PDKTModelBuilder/Models/PictureEntity.m b/Demo/PDKTModelBuilder/Models/PictureEntity.m index b946e14..d366314 100644 --- a/Demo/PDKTModelBuilder/Models/PictureEntity.m +++ b/Demo/PDKTModelBuilder/Models/PictureEntity.m @@ -16,5 +16,6 @@ @implementation PictureEntity @dynamic picturePublishedDate; @dynamic pictureURL; @dynamic author; +@dynamic pictureModificationDateUnixTimestamp; @end diff --git a/Demo/PDKTModelBuilder/PDKTModelBuilder.xcdatamodeld/PDKTModelBuilder.xcdatamodel/contents b/Demo/PDKTModelBuilder/PDKTModelBuilder.xcdatamodeld/PDKTModelBuilder.xcdatamodel/contents index ea29238..18e8963 100644 --- a/Demo/PDKTModelBuilder/PDKTModelBuilder.xcdatamodeld/PDKTModelBuilder.xcdatamodel/contents +++ b/Demo/PDKTModelBuilder/PDKTModelBuilder.xcdatamodeld/PDKTModelBuilder.xcdatamodel/contents @@ -1,7 +1,8 @@ - + + @@ -16,7 +17,7 @@ - + \ No newline at end of file diff --git a/Demo/PDKTModelBuilderTests/NSManagedObjectModelsTests.m b/Demo/PDKTModelBuilderTests/NSManagedObjectModelsTests.m index 583cef6..8d86740 100644 --- a/Demo/PDKTModelBuilderTests/NSManagedObjectModelsTests.m +++ b/Demo/PDKTModelBuilderTests/NSManagedObjectModelsTests.m @@ -70,7 +70,7 @@ - (void)testEntityUpdateDate { @"name":@"John Doe", @"email":@"john.doe@apple.com", @"blog_url":@"www.tumblr.com/johndoe" - } mutableCopy]; + } mutableCopy]; UserEntity *user = [UserEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:userDictionary]; XCTAssertNotNil(user.entityUpdateDate); @@ -89,17 +89,17 @@ - (void)testNSManagedObjectsRelationships { @"email":@"john.doe@apple.com", @"blog_url":@"www.tumblr.com/johndoe", @"pictures":@[ - @{ - @"id":@"1", - @"url":@"www.apple.com/images/picture.jpg", - @"published_on":@"1415735002" - }, - @{ - @"id":@"2", - @"url":@"www.apple.com/images/picture2.jpg", - @"published_on":@"1415735002" - } - ] + @{ + @"id":@"1", + @"url":@"www.apple.com/images/picture.jpg", + @"published_on":@"1415735002" + }, + @{ + @"id":@"2", + @"url":@"www.apple.com/images/picture2.jpg", + @"published_on":@"1415735002" + } + ] }; UserEntity *user = [UserEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:userDictionary]; @@ -121,7 +121,7 @@ - (void)testAPIResponseHotFix { @"blog":@{ @"John Doe's blog" @"url":@"www.tumblr.com/johndoe" - }, + }, @"user_pictures":@[ @{ @"id":@"1", @@ -264,5 +264,126 @@ - (void)testNSManagedObjectsRelationshipsUpdated { } } +- (void)testRemoveAfterRelationshipOneToOne { + NSDictionary *pictureDictionary = @{ + @"id": @"1", + @"published_on":@"1415735002", + @"url": @"www.apple.com/images/picture_updated.jpg", + @"author": @{ + @"id":@"1", + @"name":@"John Doe", + @"email":@"john.doe@apple.com", + @"blog_url":@"www.tumblr.com/johndoe", + }, + @"updated_at": @1437216918 + }; + PictureEntity *picture = [PictureEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:pictureDictionary]; + XCTAssertNotNil(picture.author); + XCTAssertNotNil(picture.pictureId); + + NSDictionary *pictureDictionaryUpdated = @{ + @"id": @"1", + @"published_on":@"1415735002", + @"url": @"www.apple.com/images/picture_updated.jpg", + @"author": [NSNull null], + @"updated_at": @1437216958 + }; + PictureEntity *pictureUpdate = [PictureEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:pictureDictionaryUpdated]; + XCTAssertNil(pictureUpdate.author); + XCTAssertNotNil(pictureUpdate.pictureId); +} +- (void)testRemoveAfterRelationshipOneToMany { + NSDictionary *userDictionary = @{ + @"id":@"1", + @"name":@"John Doe", + @"email":@"john.doe@apple.com", + @"blog_url":@"www.tumblr.com/johndoe", + @"updated_at": @1437216918, + @"pictures":@[ + @{ + @"id":@"1", + @"url":@"www.apple.com/images/picture.jpg", + @"published_on":@"1415735002" + }, + @{ + @"id":@"2", + @"url":@"www.apple.com/images/picture2.jpg", + @"published_on":@"1415735002" + } + ] + }; + + UserEntity *user = [UserEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:userDictionary]; + XCTAssertNotNil(user.hasPictures); + XCTAssertNotEqual(user.hasPictures.count, 0); + for (PictureEntity *picture in user.hasPictures) { + XCTAssert([picture isKindOfClass:[PictureEntity class]]); + // Check inverse relationship + XCTAssertEqualObjects(picture.author, user); + } + + NSDictionary *userUpdateRelationshipDictionary = @{ + @"id":@"1", + @"name":@"John Doe", + @"email":@"john.doe@apple.com", + @"blog_url":@"www.tumblr.com/johndoe", + @"updated_at": @1437216958, + @"pictures":@[] + }; + + UserEntity *userUpdateRelations = [UserEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:userUpdateRelationshipDictionary]; + XCTAssertNotNil(userUpdateRelations); + XCTAssertTrue([userUpdateRelations.hasPictures count] == 0); +} +- (void)testRemoveOneItemAfterRelationshipOneToMany { + NSDictionary *userDictionary = @{ + @"id":@"1", + @"name":@"John Doe", + @"email":@"john.doe@apple.com", + @"blog_url":@"www.tumblr.com/johndoe", + @"updated_at": @1437216918, + @"pictures":@[ + @{ + @"id":@"1", + @"url":@"www.apple.com/images/picture.jpg", + @"published_on":@"1415735002" + }, + @{ + @"id":@"2", + @"url":@"www.apple.com/images/picture2.jpg", + @"published_on":@"1415735002" + } + ] + }; + + UserEntity *user = [UserEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:userDictionary]; + XCTAssertNotNil(user.hasPictures); + XCTAssertNotEqual(user.hasPictures.count, 0); + for (PictureEntity *picture in user.hasPictures) { + XCTAssert([picture isKindOfClass:[PictureEntity class]]); + // Check inverse relationship + XCTAssertEqualObjects(picture.author, user); + } + + NSDictionary *userUpdateRelationshipDictionary = @{ + @"id":@"1", + @"name":@"John Doe", + @"email":@"john.doe@apple.com", + @"blog_url":@"www.tumblr.com/johndoe", + @"updated_at": @1437216958, + @"pictures":@[ + @{ + @"id":@"1", + @"url":@"www.apple.com/images/picture66.jpg", + @"published_on":@"1415735002" + } + ] + }; + + UserEntity *userUpdateRelations = [UserEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:userUpdateRelationshipDictionary]; + XCTAssertNotNil(userUpdateRelations); + XCTAssertTrue([userUpdateRelations.hasPictures count] == 1); +} + @end diff --git a/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToMany.m b/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToMany.m index d07f3cf..b4373d0 100644 --- a/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToMany.m +++ b/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToMany.m @@ -12,11 +12,17 @@ @implementation __PDKTCoreDataEntityRelationshipOneToMany - (void)parseRelationshipInDictionary:(NSDictionary *)dictionary withEntity:(NSManagedObject *)entity relationshipProperty:(NSString *)relationshipProperty inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext{ id relationshipData = [dictionary valueForKeyPath:self.keyPath]; if ([relationshipData isKindOfClass:[NSArray class]]) { - for (NSDictionary *relationshipItem in relationshipData) { - id item = [self parseItemData:relationshipItem withClass:self.relatedClass inManagedObjectContext:managedObjectContext]; - if (item) { - [self addItem:item toEntity:entity toColletionInPropertyWithName:relationshipProperty]; + NSArray *relationshipDataArray = (NSArray *)relationshipData; + if ([relationshipDataArray count] > 0) { + [entity setValue:nil forKey:relationshipProperty]; + for (NSDictionary *relationshipItem in relationshipDataArray) { + id item = [self parseItemData:relationshipItem withClass:self.relatedClass inManagedObjectContext:managedObjectContext]; + if (item) { + [self addItem:item toEntity:entity toColletionInPropertyWithName:relationshipProperty]; + } } + } else { + [entity setValue:nil forKey:relationshipProperty]; } } } diff --git a/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToOne.m b/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToOne.m index 69a8ccb..48a98f8 100644 --- a/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToOne.m +++ b/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToOne.m @@ -16,6 +16,8 @@ - (void)parseRelationshipInDictionary:(NSDictionary *)dictionary withEntity:(NSM if (item) { [entity setValue:item forKey:relationshipProperty]; } + } else if (!relationshipData || [relationshipData isEqual:[NSNull null]]) { + [entity setValue:nil forKey:relationshipProperty]; } } - (id)parseItemData:(NSDictionary *)itemData withClass:(Class)itemClass inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext{ From e46d7c40c0c29ce15228282bc263bc4c1e7c3afe Mon Sep 17 00:00:00 2001 From: Antonio Date: Thu, 10 Dec 2015 11:50:58 +0100 Subject: [PATCH 07/13] Bug fixed when the relationships are updated --- .../PDKTModelBuilder.xcdatamodel/contents | 2 +- .../NSManagedObjectModelsTests.m | 7 +++++++ .../__PDKTCoreDataEntityRelationshipOneToMany.m | 13 +++++++++++-- .../__PDKTCoreDataEntityRelationshipOneToOne.m | 4 +++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Demo/PDKTModelBuilder/PDKTModelBuilder.xcdatamodeld/PDKTModelBuilder.xcdatamodel/contents b/Demo/PDKTModelBuilder/PDKTModelBuilder.xcdatamodeld/PDKTModelBuilder.xcdatamodel/contents index 18e8963..b50bc42 100644 --- a/Demo/PDKTModelBuilder/PDKTModelBuilder.xcdatamodeld/PDKTModelBuilder.xcdatamodel/contents +++ b/Demo/PDKTModelBuilder/PDKTModelBuilder.xcdatamodeld/PDKTModelBuilder.xcdatamodel/contents @@ -1,5 +1,5 @@ - + diff --git a/Demo/PDKTModelBuilderTests/NSManagedObjectModelsTests.m b/Demo/PDKTModelBuilderTests/NSManagedObjectModelsTests.m index 8d86740..fefbb63 100644 --- a/Demo/PDKTModelBuilderTests/NSManagedObjectModelsTests.m +++ b/Demo/PDKTModelBuilderTests/NSManagedObjectModelsTests.m @@ -23,6 +23,7 @@ @implementation NSManagedObjectModelsTests - (void)setUp { [super setUp]; self.coreDataStack = [[InMemoryCoreDataStack alloc]initWithModelName:@"PDKTModelBuilder"]; + } - (NSManagedObjectContext *)managedObjectContext{ @@ -278,6 +279,7 @@ - (void)testRemoveAfterRelationshipOneToOne { @"updated_at": @1437216918 }; PictureEntity *picture = [PictureEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:pictureDictionary]; + [self.managedObjectContext save:nil]; XCTAssertNotNil(picture.author); XCTAssertNotNil(picture.pictureId); @@ -289,6 +291,7 @@ - (void)testRemoveAfterRelationshipOneToOne { @"updated_at": @1437216958 }; PictureEntity *pictureUpdate = [PictureEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:pictureDictionaryUpdated]; + [self.managedObjectContext save:nil]; XCTAssertNil(pictureUpdate.author); XCTAssertNotNil(pictureUpdate.pictureId); } @@ -314,6 +317,7 @@ - (void)testRemoveAfterRelationshipOneToMany { }; UserEntity *user = [UserEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:userDictionary]; + [self.managedObjectContext save:nil]; XCTAssertNotNil(user.hasPictures); XCTAssertNotEqual(user.hasPictures.count, 0); for (PictureEntity *picture in user.hasPictures) { @@ -332,6 +336,7 @@ - (void)testRemoveAfterRelationshipOneToMany { }; UserEntity *userUpdateRelations = [UserEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:userUpdateRelationshipDictionary]; + [self.managedObjectContext save:nil]; XCTAssertNotNil(userUpdateRelations); XCTAssertTrue([userUpdateRelations.hasPictures count] == 0); } @@ -357,6 +362,7 @@ - (void)testRemoveOneItemAfterRelationshipOneToMany { }; UserEntity *user = [UserEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:userDictionary]; + [self.managedObjectContext save:nil]; XCTAssertNotNil(user.hasPictures); XCTAssertNotEqual(user.hasPictures.count, 0); for (PictureEntity *picture in user.hasPictures) { @@ -381,6 +387,7 @@ - (void)testRemoveOneItemAfterRelationshipOneToMany { }; UserEntity *userUpdateRelations = [UserEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:userUpdateRelationshipDictionary]; + [self.managedObjectContext save:nil]; XCTAssertNotNil(userUpdateRelations); XCTAssertTrue([userUpdateRelations.hasPictures count] == 1); } diff --git a/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToMany.m b/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToMany.m index b4373d0..b195822 100644 --- a/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToMany.m +++ b/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToMany.m @@ -9,12 +9,14 @@ #import "__PDKTCoreDataEntityRelationshipOneToMany.h" @implementation __PDKTCoreDataEntityRelationshipOneToMany + + - (void)parseRelationshipInDictionary:(NSDictionary *)dictionary withEntity:(NSManagedObject *)entity relationshipProperty:(NSString *)relationshipProperty inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext{ id relationshipData = [dictionary valueForKeyPath:self.keyPath]; if ([relationshipData isKindOfClass:[NSArray class]]) { NSArray *relationshipDataArray = (NSArray *)relationshipData; if ([relationshipDataArray count] > 0) { - [entity setValue:nil forKey:relationshipProperty]; + [self removeInContext:managedObjectContext relationshipProperty:relationshipProperty entity:entity]; for (NSDictionary *relationshipItem in relationshipDataArray) { id item = [self parseItemData:relationshipItem withClass:self.relatedClass inManagedObjectContext:managedObjectContext]; if (item) { @@ -22,7 +24,7 @@ - (void)parseRelationshipInDictionary:(NSDictionary *)dictionary withEntity:(NSM } } } else { - [entity setValue:nil forKey:relationshipProperty]; + [self removeInContext:managedObjectContext relationshipProperty:relationshipProperty entity:entity]; } } } @@ -44,4 +46,11 @@ - (void)addItem:(id)item toEntity:(NSManagedObject *)entity toColletionInPropert } } } + +#pragma mark - Private +- (void)removeInContext:(NSManagedObjectContext *)managedObjectContext relationshipProperty:(NSString *)relationshipProperty entity:(NSManagedObject *)entity { + for (NSManagedObject *element in [entity valueForKey:relationshipProperty]) { + [managedObjectContext deleteObject:element]; + } +} @end diff --git a/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToOne.m b/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToOne.m index 48a98f8..02454e1 100644 --- a/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToOne.m +++ b/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToOne.m @@ -17,7 +17,9 @@ - (void)parseRelationshipInDictionary:(NSDictionary *)dictionary withEntity:(NSM [entity setValue:item forKey:relationshipProperty]; } } else if (!relationshipData || [relationshipData isEqual:[NSNull null]]) { - [entity setValue:nil forKey:relationshipProperty]; + if ([entity valueForKey:relationshipProperty]) { + [managedObjectContext deleteObject:[entity valueForKey:relationshipProperty]]; + } } } - (id)parseItemData:(NSDictionary *)itemData withClass:(Class)itemClass inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext{ From d844e1317fcc13fab96282d9060b9b835777d85a Mon Sep 17 00:00:00 2001 From: Antonio Date: Sun, 17 Jan 2016 12:21:09 +0100 Subject: [PATCH 08/13] Date transformer with time zone 0 --- .../project.pbxproj | 6 ++++ .../PDKTDateTimeZoneCeroTransformer.h | 13 +++++++ .../PDKTDateTimeZoneCeroTransformer.m | 36 +++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 PDKTModelBuilder/DataTransformers/PDKTDateTimeZoneCeroTransformer.h create mode 100644 PDKTModelBuilder/DataTransformers/PDKTDateTimeZoneCeroTransformer.m diff --git a/Demo/PDKTModelBuilder.xcodeproj/project.pbxproj b/Demo/PDKTModelBuilder.xcodeproj/project.pbxproj index ce37b63..d76b194 100644 --- a/Demo/PDKTModelBuilder.xcodeproj/project.pbxproj +++ b/Demo/PDKTModelBuilder.xcodeproj/project.pbxproj @@ -52,6 +52,7 @@ 88C4646F1A12948300A6B9D6 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 88C464641A12938200A6B9D6 /* Info.plist */; }; 88C464751A129FAD00A6B9D6 /* PictureEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C464741A129FAD00A6B9D6 /* PictureEntity.m */; }; A9D84FB31B5FA4DE003E3BD1 /* UserEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = A9D84FB21B5FA4DE003E3BD1 /* UserEntity.m */; }; + A9E7B51A1C4BB031009F8A64 /* PDKTDateTimeZoneCeroTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = A9E7B5191C4BB030009F8A64 /* PDKTDateTimeZoneCeroTransformer.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -147,6 +148,8 @@ 88C464741A129FAD00A6B9D6 /* PictureEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PictureEntity.m; sourceTree = ""; }; A9D84FB11B5FA4DE003E3BD1 /* UserEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserEntity.h; sourceTree = ""; }; A9D84FB21B5FA4DE003E3BD1 /* UserEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UserEntity.m; sourceTree = ""; }; + A9E7B5181C4BB030009F8A64 /* PDKTDateTimeZoneCeroTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDKTDateTimeZoneCeroTransformer.h; sourceTree = ""; }; + A9E7B5191C4BB030009F8A64 /* PDKTDateTimeZoneCeroTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDKTDateTimeZoneCeroTransformer.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -333,6 +336,8 @@ 883ACABB1A043815006139C6 /* PDKTDataTransformer.m */, 883ACABD1A043815006139C6 /* PDKTDateTransformer.h */, 883ACABE1A043815006139C6 /* PDKTDateTransformer.m */, + A9E7B5181C4BB030009F8A64 /* PDKTDateTimeZoneCeroTransformer.h */, + A9E7B5191C4BB030009F8A64 /* PDKTDateTimeZoneCeroTransformer.m */, 883ACABF1A043815006139C6 /* PDKTDoubleTransformer.h */, 883ACAC01A043815006139C6 /* PDKTDoubleTransformer.m */, 883ACAC11A043815006139C6 /* PDKTFloatTransformer.h */, @@ -499,6 +504,7 @@ 883ACA141A041786006139C6 /* AppDelegate.m in Sources */, 88C464751A129FAD00A6B9D6 /* PictureEntity.m in Sources */, 883ACACA1A043815006139C6 /* PDKTDataTransformer.m in Sources */, + A9E7B51A1C4BB031009F8A64 /* PDKTDateTimeZoneCeroTransformer.m in Sources */, 883ACA171A041786006139C6 /* PDKTModelBuilder.xcdatamodeld in Sources */, 883ACACC1A043815006139C6 /* PDKTDoubleTransformer.m in Sources */, 883ACA681A0417BA006139C6 /* __PDKTCoreDataEntityRelationshipOneToMany.m in Sources */, diff --git a/PDKTModelBuilder/DataTransformers/PDKTDateTimeZoneCeroTransformer.h b/PDKTModelBuilder/DataTransformers/PDKTDateTimeZoneCeroTransformer.h new file mode 100644 index 0000000..359b733 --- /dev/null +++ b/PDKTModelBuilder/DataTransformers/PDKTDateTimeZoneCeroTransformer.h @@ -0,0 +1,13 @@ +// +// PDKTDateTimeZoneCeroTransformer.h +// PDKTModelBuilder +// +// Created by Antonio on 17/1/16. +// Copyright © 2016 Produkt. All rights reserved. +// + +#import "PDKTDataTransformer.h" + +@interface PDKTDateTimeZoneCeroTransformer : PDKTDataTransformer + +@end diff --git a/PDKTModelBuilder/DataTransformers/PDKTDateTimeZoneCeroTransformer.m b/PDKTModelBuilder/DataTransformers/PDKTDateTimeZoneCeroTransformer.m new file mode 100644 index 0000000..786af4f --- /dev/null +++ b/PDKTModelBuilder/DataTransformers/PDKTDateTimeZoneCeroTransformer.m @@ -0,0 +1,36 @@ +// +// PDKTDateTimeZoneCeroTransformer.m +// PDKTModelBuilder +// +// Created by Antonio on 17/1/16. +// Copyright © 2016 Produkt. All rights reserved. +// + +#import "PDKTDateTimeZoneCeroTransformer.h" + +@implementation PDKTDateTimeZoneCeroTransformer + +- (id)tranformValueFromObject:(id)object { + if (!object || [object isEqual:[NSNull null]]) { + return nil; + } + NSString *objectDescription = [NSString stringWithFormat:@"%@", object]; + NSDate *date = nil; + NSCharacterSet *alphaNumbersSet = [NSCharacterSet decimalDigitCharacterSet]; + NSCharacterSet *stringSet = [NSCharacterSet characterSetWithCharactersInString:objectDescription]; + if ([alphaNumbersSet isSupersetOfSet:stringSet]) { + date = [NSDate dateWithTimeIntervalSince1970:[objectDescription integerValue]]; + } else { + static dispatch_once_t onceToken; + static NSDateFormatter *entyPropertyDateFormatter; + dispatch_once(&onceToken, ^{ + entyPropertyDateFormatter = [[NSDateFormatter alloc] init]; + entyPropertyDateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; + [entyPropertyDateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; + }); + date = [entyPropertyDateFormatter dateFromString:objectDescription]; + } + return date; +} + +@end From f533bbd43969179f862b4b49fdddcd456b3ba033 Mon Sep 17 00:00:00 2001 From: Antonio Date: Sat, 13 Feb 2016 11:48:45 +0100 Subject: [PATCH 09/13] Don't remove oneToOne relationShip if the data isn't in the dictionary --- .../NSManagedObjectModelsTests.m | 60 +++++++++---------- ...__PDKTCoreDataEntityRelationshipOneToOne.m | 4 -- 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/Demo/PDKTModelBuilderTests/NSManagedObjectModelsTests.m b/Demo/PDKTModelBuilderTests/NSManagedObjectModelsTests.m index fefbb63..78d993c 100644 --- a/Demo/PDKTModelBuilderTests/NSManagedObjectModelsTests.m +++ b/Demo/PDKTModelBuilderTests/NSManagedObjectModelsTests.m @@ -265,36 +265,36 @@ - (void)testNSManagedObjectsRelationshipsUpdated { } } -- (void)testRemoveAfterRelationshipOneToOne { - NSDictionary *pictureDictionary = @{ - @"id": @"1", - @"published_on":@"1415735002", - @"url": @"www.apple.com/images/picture_updated.jpg", - @"author": @{ - @"id":@"1", - @"name":@"John Doe", - @"email":@"john.doe@apple.com", - @"blog_url":@"www.tumblr.com/johndoe", - }, - @"updated_at": @1437216918 - }; - PictureEntity *picture = [PictureEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:pictureDictionary]; - [self.managedObjectContext save:nil]; - XCTAssertNotNil(picture.author); - XCTAssertNotNil(picture.pictureId); - - NSDictionary *pictureDictionaryUpdated = @{ - @"id": @"1", - @"published_on":@"1415735002", - @"url": @"www.apple.com/images/picture_updated.jpg", - @"author": [NSNull null], - @"updated_at": @1437216958 - }; - PictureEntity *pictureUpdate = [PictureEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:pictureDictionaryUpdated]; - [self.managedObjectContext save:nil]; - XCTAssertNil(pictureUpdate.author); - XCTAssertNotNil(pictureUpdate.pictureId); -} +//- (void)testRemoveAfterRelationshipOneToOne { +// NSDictionary *pictureDictionary = @{ +// @"id": @"1", +// @"published_on":@"1415735002", +// @"url": @"www.apple.com/images/picture_updated.jpg", +// @"author": @{ +// @"id":@"1", +// @"name":@"John Doe", +// @"email":@"john.doe@apple.com", +// @"blog_url":@"www.tumblr.com/johndoe", +// }, +// @"updated_at": @1437216918 +// }; +// PictureEntity *picture = [PictureEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:pictureDictionary]; +// [self.managedObjectContext save:nil]; +// XCTAssertNotNil(picture.author); +// XCTAssertNotNil(picture.pictureId); +// +// NSDictionary *pictureDictionaryUpdated = @{ +// @"id": @"1", +// @"published_on":@"1415735002", +// @"url": @"www.apple.com/images/picture_updated.jpg", +// @"author": [NSNull null], +// @"updated_at": @1437216958 +// }; +// PictureEntity *pictureUpdate = [PictureEntity updateOrInsertIntoManagedObjectContext:self.managedObjectContext withDictionary:pictureDictionaryUpdated]; +// [self.managedObjectContext save:nil]; +// XCTAssertNil(pictureUpdate.author); +// XCTAssertNotNil(pictureUpdate.pictureId); +//} - (void)testRemoveAfterRelationshipOneToMany { NSDictionary *userDictionary = @{ @"id":@"1", diff --git a/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToOne.m b/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToOne.m index 02454e1..69a8ccb 100644 --- a/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToOne.m +++ b/PDKTModelBuilder/CoreData/EntityRelationships/__PDKTCoreDataEntityRelationshipOneToOne.m @@ -16,10 +16,6 @@ - (void)parseRelationshipInDictionary:(NSDictionary *)dictionary withEntity:(NSM if (item) { [entity setValue:item forKey:relationshipProperty]; } - } else if (!relationshipData || [relationshipData isEqual:[NSNull null]]) { - if ([entity valueForKey:relationshipProperty]) { - [managedObjectContext deleteObject:[entity valueForKey:relationshipProperty]]; - } } } - (id)parseItemData:(NSDictionary *)itemData withClass:(Class)itemClass inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext{ From 0b421daec8fd6094d7a84561d431a82a9612b62c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Jim=C3=A9nez=20Mart=C3=ADnez?= Date: Tue, 1 Mar 2016 12:01:23 +0100 Subject: [PATCH 10/13] Update milliseconds --- .../DataTransformers/PDKTDateTimeZoneCeroTransformer.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PDKTModelBuilder/DataTransformers/PDKTDateTimeZoneCeroTransformer.m b/PDKTModelBuilder/DataTransformers/PDKTDateTimeZoneCeroTransformer.m index 786af4f..4519b68 100644 --- a/PDKTModelBuilder/DataTransformers/PDKTDateTimeZoneCeroTransformer.m +++ b/PDKTModelBuilder/DataTransformers/PDKTDateTimeZoneCeroTransformer.m @@ -26,7 +26,7 @@ - (id)tranformValueFromObject:(id)object { dispatch_once(&onceToken, ^{ entyPropertyDateFormatter = [[NSDateFormatter alloc] init]; entyPropertyDateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; - [entyPropertyDateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; + [entyPropertyDateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss:SSS"]; }); date = [entyPropertyDateFormatter dateFromString:objectDescription]; } From 8c3c93499083e213ecec3aa4cdc8efac4f275ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Ferna=CC=81ndez?= Date: Tue, 1 Mar 2016 13:24:32 +0100 Subject: [PATCH 11/13] added new ISO8601 date transformer with milliseconds accuracy --- .../project.pbxproj | 6 +++ .../PDKTISO8601DateTransformer.h | 13 +++++++ .../PDKTISO8601DateTransformer.m | 39 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 PDKTModelBuilder/DataTransformers/PDKTISO8601DateTransformer.h create mode 100644 PDKTModelBuilder/DataTransformers/PDKTISO8601DateTransformer.m diff --git a/Demo/PDKTModelBuilder.xcodeproj/project.pbxproj b/Demo/PDKTModelBuilder.xcodeproj/project.pbxproj index d76b194..cf2fd83 100644 --- a/Demo/PDKTModelBuilder.xcodeproj/project.pbxproj +++ b/Demo/PDKTModelBuilder.xcodeproj/project.pbxproj @@ -53,6 +53,7 @@ 88C464751A129FAD00A6B9D6 /* PictureEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C464741A129FAD00A6B9D6 /* PictureEntity.m */; }; A9D84FB31B5FA4DE003E3BD1 /* UserEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = A9D84FB21B5FA4DE003E3BD1 /* UserEntity.m */; }; A9E7B51A1C4BB031009F8A64 /* PDKTDateTimeZoneCeroTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = A9E7B5191C4BB030009F8A64 /* PDKTDateTimeZoneCeroTransformer.m */; }; + E71269DA1C85C039008DCFF4 /* PDKTISO8601DateTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = E71269D91C85C039008DCFF4 /* PDKTISO8601DateTransformer.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -150,6 +151,8 @@ A9D84FB21B5FA4DE003E3BD1 /* UserEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UserEntity.m; sourceTree = ""; }; A9E7B5181C4BB030009F8A64 /* PDKTDateTimeZoneCeroTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDKTDateTimeZoneCeroTransformer.h; sourceTree = ""; }; A9E7B5191C4BB030009F8A64 /* PDKTDateTimeZoneCeroTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDKTDateTimeZoneCeroTransformer.m; sourceTree = ""; }; + E71269D81C85C039008DCFF4 /* PDKTISO8601DateTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDKTISO8601DateTransformer.h; sourceTree = ""; }; + E71269D91C85C039008DCFF4 /* PDKTISO8601DateTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDKTISO8601DateTransformer.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -348,6 +351,8 @@ 883ACAC61A043815006139C6 /* PDKTStringTransformer.m */, 883ACAC71A043815006139C6 /* PDKTURLTransformer.h */, 883ACAC81A043815006139C6 /* PDKTURLTransformer.m */, + E71269D81C85C039008DCFF4 /* PDKTISO8601DateTransformer.h */, + E71269D91C85C039008DCFF4 /* PDKTISO8601DateTransformer.m */, ); path = DataTransformers; sourceTree = ""; @@ -508,6 +513,7 @@ 883ACA171A041786006139C6 /* PDKTModelBuilder.xcdatamodeld in Sources */, 883ACACC1A043815006139C6 /* PDKTDoubleTransformer.m in Sources */, 883ACA681A0417BA006139C6 /* __PDKTCoreDataEntityRelationshipOneToMany.m in Sources */, + E71269DA1C85C039008DCFF4 /* PDKTISO8601DateTransformer.m in Sources */, 883ACA771A0417BA006139C6 /* PDKTEntityDataParser.m in Sources */, 883ACA1A1A041786006139C6 /* ViewController.m in Sources */, 883ACACB1A043815006139C6 /* PDKTDateTransformer.m in Sources */, diff --git a/PDKTModelBuilder/DataTransformers/PDKTISO8601DateTransformer.h b/PDKTModelBuilder/DataTransformers/PDKTISO8601DateTransformer.h new file mode 100644 index 0000000..4d4b9f2 --- /dev/null +++ b/PDKTModelBuilder/DataTransformers/PDKTISO8601DateTransformer.h @@ -0,0 +1,13 @@ +// +// PDKTISO8601DateTransformer.h +// PDKTModelBuilder +// +// Created by sergio on 01/03/16. +// Copyright © 2016 Produkt. All rights reserved. +// + +#import "PDKTDataTransformer.h" + +@interface PDKTISO8601DateTransformer : PDKTDataTransformer + +@end diff --git a/PDKTModelBuilder/DataTransformers/PDKTISO8601DateTransformer.m b/PDKTModelBuilder/DataTransformers/PDKTISO8601DateTransformer.m new file mode 100644 index 0000000..d46ca73 --- /dev/null +++ b/PDKTModelBuilder/DataTransformers/PDKTISO8601DateTransformer.m @@ -0,0 +1,39 @@ +// +// PDKTISO8601DateTransformer.m +// PDKTModelBuilder +// +// Created by sergio on 01/03/16. +// Copyright © 2016 Produkt. All rights reserved. +// + +#import "PDKTISO8601DateTransformer.h" + +@implementation PDKTISO8601DateTransformer + +- (id)tranformValueFromObject:(id)object { + // Returns a NSDate object that corresponds to the specified RFC 3339 date time string. + + if (!object || [object isEqual:[NSNull null]]) { + return nil; + } + NSString *objectDescription = [NSString stringWithFormat:@"%@", object]; + NSDate *date = nil; + NSCharacterSet *alphaNumbersSet = [NSCharacterSet decimalDigitCharacterSet]; + NSCharacterSet *stringSet = [NSCharacterSet characterSetWithCharactersInString:objectDescription]; + if ([alphaNumbersSet isSupersetOfSet:stringSet]) { + date = [NSDate dateWithTimeIntervalSince1970:[objectDescription integerValue]]; + } else { + static dispatch_once_t onceToken; + static NSDateFormatter *entityPropertyDateFormatter; + dispatch_once(&onceToken, ^{ + entityPropertyDateFormatter = [[NSDateFormatter alloc] init]; + entityPropertyDateFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; + entityPropertyDateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; + [entityPropertyDateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZ"]; + }); + date = [entityPropertyDateFormatter dateFromString:objectDescription]; + } + return date; +} + +@end From 40c4e30d5daa73fc12210f24c70b987eda3a82a0 Mon Sep 17 00:00:00 2001 From: Antonio Date: Tue, 1 Mar 2016 17:10:47 +0100 Subject: [PATCH 12/13] Remove milliseconds in DateTimeCeroTime transformer --- .../DataTransformers/PDKTDateTimeZoneCeroTransformer.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PDKTModelBuilder/DataTransformers/PDKTDateTimeZoneCeroTransformer.m b/PDKTModelBuilder/DataTransformers/PDKTDateTimeZoneCeroTransformer.m index 4519b68..786af4f 100644 --- a/PDKTModelBuilder/DataTransformers/PDKTDateTimeZoneCeroTransformer.m +++ b/PDKTModelBuilder/DataTransformers/PDKTDateTimeZoneCeroTransformer.m @@ -26,7 +26,7 @@ - (id)tranformValueFromObject:(id)object { dispatch_once(&onceToken, ^{ entyPropertyDateFormatter = [[NSDateFormatter alloc] init]; entyPropertyDateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; - [entyPropertyDateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss:SSS"]; + [entyPropertyDateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; }); date = [entyPropertyDateFormatter dateFromString:objectDescription]; } From f14f8d34115e2a30c695167f87e37f917d3bd411 Mon Sep 17 00:00:00 2001 From: Antonio Date: Tue, 5 Apr 2016 16:30:26 +0200 Subject: [PATCH 13/13] Remove locale identifier --- PDKTModelBuilder/DataTransformers/PDKTISO8601DateTransformer.m | 1 - 1 file changed, 1 deletion(-) diff --git a/PDKTModelBuilder/DataTransformers/PDKTISO8601DateTransformer.m b/PDKTModelBuilder/DataTransformers/PDKTISO8601DateTransformer.m index d46ca73..d2f6fec 100644 --- a/PDKTModelBuilder/DataTransformers/PDKTISO8601DateTransformer.m +++ b/PDKTModelBuilder/DataTransformers/PDKTISO8601DateTransformer.m @@ -27,7 +27,6 @@ - (id)tranformValueFromObject:(id)object { static NSDateFormatter *entityPropertyDateFormatter; dispatch_once(&onceToken, ^{ entityPropertyDateFormatter = [[NSDateFormatter alloc] init]; - entityPropertyDateFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; entityPropertyDateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; [entityPropertyDateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZ"]; });