【发布时间】: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>) ) -
我认为我缺乏理解与托管对象上下文有关。
-
那里的错误只是意味着数据还没有加载到内存中-不用担心
标签: ios objective-c json core-data restkit