我正在尝试使用RestKit来检索事件列表,我一直这样做:
2013-05-20 10:52:56.708 EventApp[3380:c07] I restkit:RKLog.m:34 RestKit logging initialized...
2013-05-20 10:52:56.773 EventApp[3380:c07] *** Assertion failure in -[RKObjectRequestOperation initWithRequest:responseDescriptors:], /Users/mitchell/Desktop/eventapp/take2/EventApp/Pods/RestKit/Code/Network/RKObjectRequestOperation.m:158
2013-05-20 10:52:56.774 EventApp[3380:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: responseDescriptors'
我在这个问题上已经好几天了。由于我的iOS开发技能(每年大约一个项目)存在相当大的差距,如果有人能够使用一些非专业术语引导我朝着正确的方向前进,那将会非常有帮助。
请考虑我特意使用enqueueObjectRequestOperation来批量处理多个请求。我在这里拼凑了一些代码用于翻译。
这是我的数据模型的样子:
以下是JSON文件的样子:
[{
"id":1,
"farm_id":1,
"all_day": "NO",
"from": "2013-05-08T18:45:38Z",
"to": "2013-05-08T18:45:38Z",
"name": "event 1",
"desc": "some description",
"photo": "some.png",
"price": "price"
}]
这是我的代码:
NSManagedObjectContext *context;
RKObjectManager *objectManager;
if (self.eventContext == nil) {
NSError *error = nil;
NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"FarmApp" ofType:@"momd"]];
RKEntityMapping *entityMapping;
// NOTE: Due to an iOS 5 bug, the managed object model returned is immutable.
NSManagedObjectModel *managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
// Initialize the Core Data stack
[managedObjectStore createPersistentStoreCoordinator];
NSPersistentStore __unused *eventPersistentStore = [managedObjectStore addInMemoryPersistentStore:&error];
NSAssert(eventPersistentStore, @"Failed to add persistent store: %@", error);
[managedObjectStore createManagedObjectContexts];
// Set the default store shared instance
[RKManagedObjectStore setDefaultStore:managedObjectStore];
// Configure the object manager
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://sandbox.bm.com"]];
[RKObjectManager setSharedManager:objectManager];
[objectManager setRequestSerializationMIMEType:@"application/json"];
[objectManager setAcceptHeaderWithMIMEType:@"text/plain"];
objectManager.managedObjectStore = managedObjectStore;
entityMapping = [RKEntityMapping mappingForEntityForName:@"Event" inManagedObjectStore:managedObjectStore];
[entityMapping addAttributeMappingsFromDictionary:@{
@"id": @"eventID",
@"farm_id": @"farm",
@"all_day": @"allDay",
@"from": @"from",
@"to": @"to",
@"name": @"name",
@"desc": @"desc",
@"photo": @"photo",
@"price": @"price"
}];
RKResponseDescriptor *successDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:entityMapping pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:successDescriptor];
RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:entityMapping pathPattern:nil keyPath:@"errors" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError)];
[objectManager addResponseDescriptor:errorDescriptor];
self.eventContext = managedObjectStore.mainQueueManagedObjectContext;
}
context = self.eventContext;
NSString* url = [NSString stringWithFormat:@"http://sandbox.bm.com/farmapp/%@.json", @"events"];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:[objectManager responseDescriptors]];
[operation setCompletionBlockWithSuccess:nil failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(@"Loaded this error: %@", [error localizedDescription]);
}];
NSArray *operations = [NSArray arrayWithObjects:operation, nil];
for (int i = 0; i < [operations count]; i++ ) {
[[RKObjectManager sharedManager] enqueueObjectRequestOperation:[operations objectAtIndex:i]];
}
有人可以帮助我吗?
以下是最终解决方案
if (self.eventContext == nil) {
NSManagedObjectContext *context;
RKObjectManager *objectManager;
NSError *error = nil;
NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"FarmApp" ofType:@"momd"]];
RKEntityMapping *entityMapping;
// NOTE: Due to an iOS 5 bug, the managed object model returned is immutable.
NSManagedObjectModel *managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
// Initialize the Core Data stack
[managedObjectStore createPersistentStoreCoordinator];
NSPersistentStore __unused *eventPersistentStore = [managedObjectStore addInMemoryPersistentStore:&error];
NSAssert(eventPersistentStore, @"Failed to add persistent store: %@", error);
[managedObjectStore createManagedObjectContexts];
// Set the default store shared instance
[RKManagedObjectStore setDefaultStore:managedObjectStore];
// Configure the object manager
objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://sandbox.bm.com"]];
[RKObjectManager setSharedManager:objectManager];
[objectManager setRequestSerializationMIMEType:@"application/json"];
[objectManager setAcceptHeaderWithMIMEType:@"text/plain"];
objectManager.managedObjectStore = managedObjectStore;
entityMapping = [RKEntityMapping mappingForEntityForName:@"Event" inManagedObjectStore:managedObjectStore];
[entityMapping addAttributeMappingsFromDictionary:@{
@"id": @"eventID",
//@"farm_id": @"farm",-->cannot create relationship this way
@"farm_id" : @"farmID",//farmID attribute needs to be added to Event's model
@"all_day": @"allDay",
@"from": @"from",
@"to": @"to",
@"name": @"name",
@"desc": @"desc",
@"photo": @"photo",
@"price": @"price"
}];
[entityMapping addConnectionForRelationship:@"farm" connectedBy:@"farmID"];
RKResponseDescriptor *successDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:entityMapping pathPattern:nil keyPath:@"events" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:successDescriptor];
RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:entityMapping pathPattern:nil keyPath:@"errors" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError)];
[objectManager addResponseDescriptor:errorDescriptor];
self.eventContext = managedObjectStore.mainQueueManagedObjectContext;
context = self.eventContext;
NSString* url = [NSString stringWithFormat:@"http://sandbox.bm.com/farmapp/%@.json", @"events"];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
RKManagedObjectRequestOperation *operation = [objectManager managedObjectRequestOperationWithRequest:request managedObjectContext:managedObjectStore.mainQueueManagedObjectContext success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(@"Success");
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(@"Failure");
}];
NSArray *operations = [NSArray arrayWithObjects:operation, nil];
for (int i = 0; i < [operations count]; i++ ) {
[[RKObjectManager sharedManager] enqueueObjectRequestOperation:[operations objectAtIndex:i]];
}
}
答案 0 :(得分:1)
作为@JoelH。在他的一条评论中建议,你需要使用RKManagedObjectRequestOperation而不是RKObjectRequestOperation。
例如:
RKManagedObjectRequestOperation *operation = [objectmanager managedObjectRequestOperationWithRequest:request managedObjectContext:managedObjectStore.mainQueueManagedObjectContext success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(@"Success");
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(@"Failure");
}];
此外,我认为你的映射方式
@"farm_id": @"farm"
不正确。
如果要构建Event和Farm之间的关系,则需要使用以下方法之一: relationshipMappingFromKeyPath:toKeyPath:withMapping: 或addConnectionForRelationship:connectedBy:
如果Farm对象已经存在而您只想映射新事件,我会选择addConnectionForRelationship:connectedBy:
例如:
RKEntityMapping* eventMapping = [RKEntityMapping mappingForEntityForName:@"Event" inManagedObjectStore:managedObjectStore];
[entityMapping addAttributeMappingsFromDictionary:@{
@"id": @"eventID",
//@"farm_id": @"farm",-->cannot create relationship this way
@"farm_id" : @"farmID",//farmID attribute needs to be added to Event's model
@"all_day": @"allDay",
@"from": @"from",
@"to": @"to",
@"name": @"name",
@"desc": @"desc",
@"photo": @"photo",
@"price": @"price"
}];
[eventMapping addConnectionForRelationship:@"farm" connectedBy:@"farmID"];
还需要在事件模型中添加farmID属性,即RestKit does not allow relationship connection without intermediary attributes。
答案 1 :(得分:0)
RestKit文档(Mapping Without KVC)似乎暗示如果您在顶层没有KVC标签(例如events:[]
),则解析器需要pathPattern:
知道要使用哪个映射。由于您keyPath:
的{{1}}和pathPattern:
都nil
,我有两个建议:
如果可以更改JSON结构,请将顶级更改为successDescriptor
并将{ events:[...] }
更改为keyPath:nil
以反映此更改。
如果无法做到,请将keyPath:@"events"
更改为pathPattern:nil
注意,我设置pathPattern:@"/farmapp"
以匹配您的资源网址。如果您还有从该URL分支的其他类型的资源,则第二个建议可能无效。
另外,我注意到您的pathPattern:
使用与errorDescriptor
相同的映射(entityMapping
)。我不知道这是不是你想要的,但是如果你的错误响应应该是一些不同的错误对象,我建议改变它。
希望这有帮助!