RestKit并以NSManagedObject方式保存到CoreData

我正在使用RestKit ,我想parsing和保存元素到核心数据。 我有两个json文件:

第一(类别):

[ { "cat_id": 3371, "cat_name": "myName", "image": 762 }, { "cat_id": 3367, "cat_name": "anotherName", "image": 617 } ] 

和第二(元素):

 [ { "art_id": "1", "node": { "author": "name" }, "small_url": 0 }, { "art_id": "12", "node": { "author": "anotherName" }, "small_url": 0 } ] 

所以基本的想法是每个类别都有一些内部元素。 所以这是我的CoreData结构: 在这里输入图像说明

我已经下载了restkit示例,并使用TwitterCoreData示例。 我的代码是: AppDelegeta.m

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSURL *baseURL = [NSURL URLWithString:@"http://globalURL.com"]; RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:baseURL]; NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil]; RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel]; objectManager.managedObjectStore = managedObjectStore; RKEntityMapping *categoryMapping = [RKEntityMapping mappingForEntityForName:@"Category" inManagedObjectStore:managedObjectStore]; categoryMapping.identificationAttributes = @[ @"catId" ]; [categoryMapping addAttributeMappingsFromDictionary:@{ @"cat_id": @"catId", @"node.author": @"author", }]; RKEntityMapping *elementsMapping = [RKEntityMapping mappingForEntityForName:@"Elements" inManagedObjectStore:managedObjectStore]; elementsMapping.identificationAttributes = @[ @"artId" ]; [elementsMapping addAttributeMappingsFromDictionary:@{ @"art_id": @"artId", @"node.author": @"author", }]; [elementsMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"category" toKeyPath:@"category" withMapping:categoryMapping]]; RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:elementsMapping pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]; [objectManager addResponseDescriptor:responseDescriptor]; [managedObjectStore createPersistentStoreCoordinator]; NSString *storePath = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"MyCoreData.sqlite"]; NSString *seedPath = [[NSBundle mainBundle] pathForResource:@"MyCoreData" ofType:@"sqlite"]; NSError *error; NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:storePath fromSeedDatabaseAtPath:seedPath withConfiguration:nil options:nil error:&error]; NSAssert(persistentStore, @"Failed to add persistent store with error: %@", error); // Create the managed object contexts [managedObjectStore createManagedObjectContexts]; // Configure a managed object cache to ensure we do not create duplicate objects managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext]; self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; } 

ViewController.m

 NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Elements"]; NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"artId" ascending:NO]; fetchRequest.sortDescriptors = @[descriptor]; [[RKObjectManager sharedManager] getObjectsAtPath:@"/detailaddress/:catId" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { RKLogInfo(@"Load complete: Table should refresh..."); NSLog(@"%@",mappingResult); [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:@"LastUpdatedAt"]; [[NSUserDefaults standardUserDefaults] synchronize]; } failure:^(RKObjectRequestOperation *operation, NSError *error) { RKLogError(@"Load failed with error: %@", error); }]; 

和日志的映射显示我“无”。 如何使用restkit将我的第一个json(类别)的数据保存到核心数据中? 回想一下,我还没有元素列表。

当我使用创build新文件来创buildNEManagedObject子类我有Elements类。

 @interface Elements : NSManagedObject @property (nonatomic, retain) NSNumber * artId; @property (nonatomic, retain) NSString * author; @property (nonatomic, retain) NSString * title; @property (nonatomic, retain) NSManagedObject *category; @end 

几个月前,我使用RESTKit直到.20版本。 老实说,虽然这个图书馆有很好的意图,但根据我的经验,最终浪费的时间比以前想要拯救我的时间要多得多。

我用它与.NET / MVC,PHP,Python / Django / TastyPie创build的API,并用Twitter做了一些事情。 这一切都最终成为一个非常有趣的学术演习,但最终还不止于此。 RESTKIT的旧版本/新版本都会假设你的API将会响应请求。

在.10版本中,通过使用Obj-C块,可以进行大量的自定义。 我可以拦截RKRequest的请求/响应,几乎可以覆盖RESTKit要做的任何事情。 这似乎相当真棒。 现在的.20版本,一切都变得非常聪明 (聪明的代码通常不好)。

RK现在不是为了保持通用性和可塑性,而是为你做各种“方便”的事情。 这有效地消除了将其卡入API所采取的任何(非理想化和现实)形状的能力。 在这一点上,我已经回到使用AFNetworking编写我的所有代码。 我宁愿花费额外的时间来写我自己的parsing代码,并知道当我的unit testing通过,我完成了。 不要花费数小时试图让RK注销有意义的错误消息。

RK的另一个真正的问题是,它不占线下线。 它的devise假定您的应用程序总是在线,并简单地镜像在天空中的持久存储。 我的应用程序都处理iOS设备上的内容创build,在内容创build时可能不会在线。 这是我“定制”RK .10的主要原因。 当我看到.20的变化时,我决定就够了,回到原来的做法

也许我只是写自己的CRUD / RESTful框架,因为我开始厌倦了花时间使用非常专业化的库,试图尽可能less的责任留给应用程序开发人员尽一切努力。 像这样的框架往往是瑞士军刀。 他们在纸上看起来真棒, 他们可以做任何事情,然后你实际上试图削减一些东西,刀片太钝或脱落。 好的软件很less做很好的事情,如果这听起来真的太好了,可能就是这样。

所以你已经为每个NSManagedObject创build了映射(而且他们工作),但是现在你想要build立“Category”和“Elements”之间的关系。

问题是没有一个元素映射的信息,其中每个元素所属的类别(唯一的关键字是缺失的)。 因此,您需要将Cat_id添加到Elements JSON以确保此Keypath可用。

 // Elements JSON [ { "cat_id": "1313", "art_id": "1", "node": { "author": "name" }, "small_url": 0 }, ... ] // Edit keypath in relationship mapping [elementsMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"cat_id" toKeyPath:@"category" withMapping:categoryMapping]]; 

另外,您可以使用以下方法来跟踪映射是否工作。

 1) -com.apple.CoreData.SQLDebug 1 // Add in "Arguments" Tab > "Arguments Passed On Launch" 2) RKLogConfigureByName("RestKit/*", RKLogLevelTrace); // Add to AppDelegate` 

编辑

制图

你有没有更新您的数据模型中的实体Elements和您的NSManagedObject给定的值? 好像你没有。

 @interface Elements : NSManagedObject @property (nonatomic, retain) NSNumber * catId; @property (nonatomic, retain) NSNumber * artId; @property (nonatomic, retain) NSString * author; @property (nonatomic, retain) NSString * title; @property (nonatomic, retain) NSManagedObject *category; @end 

路由

您用于获取请求的path将不起作用,因为@"/detailaddress/:catId"不是有效的path。 一方面可以设置对象pipe理器的路由或者定义响应描述。

  // Route for get operation [[RKObjectManager sharedManager].router.routeSet addRoute:[RKRoute routeWithClass:[Category class] pathPattern:@"/detailaddress/:catId" method:RKRequestMethodGET]]; // Response descriptor taken from the Core Data same application RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:categoryMapping pathPattern:@"/detailaddress/:catId" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]; [objectManager addResponseDescriptor:responseDescriptor]; // Use general path for get request [[RKObjectManager sharedManager] getObjectsAtPath:@"/detailaddress" ... 

但请检查映射和数据模型是否像预期的那样设置。