如何使用 RestKit 将嵌套的 JSON 对象存储到核心数据中
Posted
技术标签:
【中文标题】如何使用 RestKit 将嵌套的 JSON 对象存储到核心数据中【英文标题】:How to store nested JSON object into Core Data using RestKit 【发布时间】:2014-04-16 14:22:34 【问题描述】:我正在尝试实现一个我认为非常简单的用例,但我不确定如何正确执行它。
当在我的应用程序中加载特定屏幕时,我需要调用返回嵌套 JSON 对象的 Web 服务,然后解析所有数据并保存到一系列 Core Data 托管对象中。每当用户离开并返回该屏幕时,我想用从服务器返回的新数据替换当前在我的 Core Data 存储中的所有数据。
这是高级概述。看起来很简单。
setupRestKit
在应用加载时被调用:
+ (void)setupRestKit
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:BASE_URL]];
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:@"application/vnd.collection+json"];
NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"Mobile" ofType:@"momd"]];
NSManagedObjectModel *managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
[managedObjectStore createPersistentStoreCoordinator];
NSString *documentPath = [NIAppDelegate applicationDocumentsDirectory].relativePath;
NSError *error;
[managedObjectStore addSQLitePersistentStoreAtPath:[NSString stringWithFormat:@"%@/Mobile.sqlite", documentPath]
fromSeedDatabaseAtPath:nil
withConfiguration:nil
options:nil
error:&error];
[managedObjectStore createManagedObjectContexts];
manager.managedObjectStore = managedObjectStore;
NSArray *rkClasses = [self allNIRestKitClasses];
NSArray *descriptors = [self allDescriptorsFromRKClasses:rkClasses];
[manager addResponseDescriptorsFromArray:descriptors];
第 25 行的 NSArray *descriptors
填充了一个描述符数组,其中包括以下返回的描述符对象:
+ (RKResponseDescriptor *)getDescriptor
RKManagedObjectStore *store = [RKObjectManager sharedManager].managedObjectStore;
RKEntityMapping *scheduleMapping = [RKEntityMapping mappingForEntityForName:@"Schedule" inManagedObjectStore:store];
[scheduleMapping addAttributeMappingsFromDictionary:@@"version": @"version",
@"href": @"href"];
RKEntityMapping *scheduleItemMapping = [RKEntityMapping mappingForEntityForName:@"ScheduleItem" inManagedObjectStore:store];
[scheduleItemMapping addAttributeMappingsFromDictionary:@@"href": @"href"];
RKEntityMapping *scheduleDataMapping = [RKEntityMapping mappingForEntityForName:@"ScheduleData" inManagedObjectStore:store];
[scheduleDataMapping addAttributeMappingsFromDictionary:@@"AllCurricConfirmed": @"allCurricConfirmed",
@"EndDateTime": @"endDateTime",
@"EventLocation": @"eventLocation",
@"Notes": @"notes",
@"RecordID": @"recordID",
@"ScheduleType": @"scheduleType",
@"StartDateTime": @"startDateTime",
@"Title": @"title"];
RKEntityMapping *scheduleLinkMapping = [RKEntityMapping mappingForEntityForName:@"ScheduleLink" inManagedObjectStore:store];
[scheduleLinkMapping addAttributeMappingsFromDictionary:@@"rel": @"rel",
@"href": @"href"];
RKRelationshipMapping *scheduleLinksInScheduleItem = [RKRelationshipMapping relationshipMappingFromKeyPath:@"link"
toKeyPath:@"scheduleLinks"
withMapping:scheduleLinkMapping];
[scheduleItemMapping addPropertyMapping:scheduleLinksInScheduleItem];
RKRelationshipMapping *scheduleDatasInScheduleItem = [RKRelationshipMapping relationshipMappingFromKeyPath:@"data"
toKeyPath:@"scheduleDatas"
withMapping:scheduleDataMapping];
[scheduleItemMapping addPropertyMapping:scheduleDatasInScheduleItem];
RKRelationshipMapping *scheduleItemsInSchedule = [RKRelationshipMapping relationshipMappingFromKeyPath:@"items"
toKeyPath:@"scheduleItems"
withMapping:scheduleItemMapping];
[scheduleMapping addPropertyMapping:scheduleItemsInSchedule];
NSIndexSet *scheduleStatusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKResponseDescriptor *scheduleDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:scheduleMapping
method:RKRequestMethodGET
pathPattern:nil
keyPath:@"collection"
statusCodes:scheduleStatusCodes];
return scheduleDescriptor;
那些描述符和关系完全包含我的嵌套 JSON 对象,我相信它们可以正常工作。
我想我的问题是 RestKit 和 Core Data 如何协同工作。我对这两种技术都比较陌生。以下 sn-p 描述了我的 ViewController 为从 web 服务获取数据所做的工作:
// ViewController.m
- (void)getData
[SVProgressHUD showWithStatus:@"Downloading Schedule"];
[NIRestKitSchedule getScheduleWithBlock:^(BOOL valid)
if (valid)
// get the data from Core Data (because I assume that RestKit has saved everything into it already?)
NSManagedObjectContext *mainContext = RKObjectManager.sharedManager.managedObjectStore.mainQueueManagedObjectContext;
NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:@"Schedule"];
NSArray *schedule = [mainContext executeFetchRequest:fetch error:nil];
// TODO: and do stuff with it
[SVProgressHUD dismiss];
else
[SVProgressHUD showErrorWithStatus:@"Could not get Schedule"];
];
// NIRestKitSchedule.m
+ (void)getScheduleWithBlock:(void (^)(BOOL))valid
[self deleteEntity:@"Schedule"];
NSURL *scheduleUrl = [RKObjectManager sharedManager].baseURL;
scheduleUrl = [scheduleUrl URLByAppendingPathComponent:SCHEDULE_ENDPOINT];
scheduleUrl = [scheduleUrl URLByAppendingDefaultParameters];
[[RKObjectManager sharedManager] getObjectsAtPath:[scheduleUrl absoluteString]
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
valid(YES);
failure:^(RKObjectRequestOperation *operation, NSError *error)
valid(NO);
];
+ (void)deleteEntity:(NSString *)entityName
NSManagedObjectContext *mainContext = [RKObjectManager sharedManager].managedObjectStore.mainQueueManagedObjectContext;
NSFetchRequest *fetchObjects = [[NSFetchRequest alloc] init];
[fetchObjects setEntity:[NSEntityDescription entityForName:entityName inManagedObjectContext:mainContext]];
[fetchObjects setIncludesPropertyValues:NO];
NSError *error = nil;
NSArray *objects = [mainContext executeFetchRequest:fetchObjects error:&error];
for (NSManagedObject *object in objects)
[mainContext deleteObject:object];
NSError *saveError = nil;
[mainContext save:&saveError];
在编译应用程序并首次运行时,最后一个代码 sn-p 中的schedule
正确加载了嵌套的数据数组。但随后对getData
的任何调用都会导致Core Data “故障”。
我应该打电话给getObjectsAtPath:parameters:success:failure
吗?我应该在哪些上下文中存储和删除我的日程安排数据?有人可以指出我正确的方向吗? RestKit 现在有点让我不知所措。
【问题讨论】:
当您说“故障”时,您的意思是日志语句中打印的内容? @Wain 正确:(lldb) po schedule <_PFArray 0x14dd6c80>( <Schedule: 0x14d6f190> (entity: Schedule; id: 0x14d32c60 <x-coredata://D88456A9-CBDD-4E92-B746-989C5E00B459/Schedule/p3> ; data: <fault>) )
我认为我缺乏理解与托管对象上下文有关。
那里的错误只是意味着数据还没有加载到内存中-不用担心
【参考方案1】:
您的代码通常应该使用mainQueueManagedObjectContext
,这样看起来不错。
当你想保存时,你应该在上下文中调用saveToPersistentStore:
而不是save:
。
是的,您应该调用 getObjectsAtPath:parameters:success:failure
,因为这是从服务器获取数据的原因。
您不需要自己删除对象,请查看fetch request blocks。
【讨论】:
好的!在我的deleteEntity:
方法中调用saveToPersistentStore:
而不是save:
可以清除我的Core Data 故障,非常感谢!现在我将研究获取请求块以及它们与删除托管对象的关系。
可能会有所帮助:***.com/questions/21232402/…以上是关于如何使用 RestKit 将嵌套的 JSON 对象存储到核心数据中的主要内容,如果未能解决你的问题,请参考以下文章
RestKit RKObjectMapping .. 嵌套和一次性对象