this is my first question here :)
OK so I have a projet with ReskKit 0.23.3 via cocoapods. I use RestKit/CoreData.
I fetch an URL, the result got mapped to my object and is correctly saved by core data. I want to use Key-Value Validation to check some values retrieved against the one already persisted. I read that i could use the methods validateKey:error:
on my NSManagedObject
. Somehow, it is never called. I'm frustrated...
Here are my files (for simplicity, i concatenated logic code into one flat file here):
JSON response /collections/{id}
{
"id": "00000000-0000-0000-0000-00000000000",
"image_url": "http://server/image.png",
"name": "Collection C",
"etag": 42,
"ctag": 42
}
Collection.h
@interface Collection : NSManagedObject
@property(nonatomic, strong) NSString *collectionId;
@property(nonatomic, strong) NSString *name;
@property(nonatomic, strong) NSURL *imageUrl;
@property(nonatomic, strong) NSNumber *etag;
@property(nonatomic, strong) NSNumber *ctag;
@end
Collection.m
@implementation Collection
@dynamic collectionId, name, imageUrl, etag, ctag;
- (BOOL)validateCollectionId:(id *)ioValue error:(NSError **)outError {
NSLog(@"Validating id");
NSLog(@"Coredata collection id: %@", self.collectionId);
NSLog(@"GET collection id: %@", (NSString *)*ioValue);
return YES;
}
- (BOOL)validateEtag:(id *)ioValue error:(NSError **)outError {
NSLog(@"Validating etag");
NSLog(@"Coredata collection etag: %@", self.etag);
NSLog(@"GET collection etag: %@", (NSString *)*ioValue);
return YES;
}
@end
Code
NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
[managedObjectStore createPersistentStoreCoordinator];
NSString *storePath = [RKApplicationDataDirectory() stringByAppendingString:@"/MyApp.sqlite"];
NSError *error;
NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:storePath fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error];
NSAssert(persistentStore, @"Failed to add persistent store with error: %@", error);
[managedObjectStore createManagedObjectContexts];
managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
[RKManagedObjectStore setDefaultStore:managedObjectStore];
NSURL *url = [NSURL URLWithString:@"http://server/api"];
RKObjectManager *objectManager = [self managerWithBaseURL:url];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
objectManager.managedObjectStore = [RKManagedObjectStore defaultStore];
RKEntityMapping *collectionMapping = [RKEntityMapping mappingForEntityForName:@"Collection" inManagedObjectStore:[RKManagedObjectStore defaultStore]];
[collectionMapping addAttributeMappingsFromDictionary:@{@"id": @"collectionId",
@"image_url": @"imageUrl"}];
[collectionMapping addAttributeMappingsFromArray:@[@"name", @"etag", @"ctag"]];
[collectionMapping setIdentificationAttributes:@[@"collectionId"]];
RKResponseDescriptor *collectionResponseDescriptors = [RKResponseDescriptor responseDescriptorWithMapping:collectionMapping
method:RKRequestMethodGET pathPattern:@"collections/:collectionId"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:collectionResponseDescriptor];
[objectManager getObjectsAtPath:@"collections/00000000-0000-0000-0000-00000000000" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
Collection *collection = (Collection *)[mappingResult.array firstObject];
NSLog(@"Collection: %@", collection);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(@"Oh noes :(");
}];
Output
2014-09-13 12:39:04.242 MyApp[41958:607] I restkit:RKLog.m:33 RestKit logging initialized...
2014-09-13 12:39:05.028 MyApp[41890:607] Collection: <NSManagedObject: 0x9108a60> (entity: Collection; id: 0x94166d0 <x-coredata://6645F428-7631-45F0-A8AF-E2352C50F35E/Collection/p1> ; data: {
collectionId = "00000000-0000-0000-0000-00000000000";
ctag = 42;
etag = 42;
imageUrl = "http://server/image.png";
name = "Collection C";
})
So, I get my Log with the Collection, but None of the NSLog in the validate<Key>:error:
methods got triggered... Could not figure out why!
Edit
With some breaks, i figured this is RKMappingOperation who is responsible for calling those validation methods on my object. Precisely it's validateValue:atKeyPath:
RKMappingOperation.m
...
- (BOOL)validateValue:(id *)value atKeyPath:(NSString *)keyPath
{
BOOL success = YES;
if (self.objectMapping.performsKeyValueValidation && [self.destinationObject respondsToSelector:@selector(validateValue:forKeyPath:error:)]) {
NSError *validationError;
success = [self.destinationObject validateValue:value forKeyPath:keyPath error:&validationError];
...
}
...
But self.destinationObject
is an NSManagedObject
and not a Collection
object...
Console
(lldb) po [self.destinationObject class]
NSManagedObject
I hope you could lead me to the right way :) Thank you!
It appears that you have not specified that the entity should use the Collection
class in the Core Data model. If you don't specify anything then NSManagedObject
will be used by default.