0

我正在尝试使用 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]];
    }

}
4

2 回答 2

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"];   

它还需要在 Event 模型中添加一个 farmID 属性,因为 RestKit还不允许没有中间属性的关系连接

于 2013-05-21T09:00:04.700 回答
0

RestKit 文档(没有 KVC 的映射)似乎暗示如果您在顶层(例如events:[])没有 KVC 标签,pathPattern:则解析器需要 a 才能知道要使用哪个映射。由于 yourkeyPath:pathPattern:are nilfor your successDescriptor,我有两个建议:

  1. 如果可以更改 JSON 结构,请将顶层更改为{ events:[...] }并更改keyPath:nilkeyPath:@"events"以反映此更改。

  2. 如果不可能,请更改pathPattern:nilpathPattern:@"/farmapp"通知,我设置pathPattern:为匹配您的资源 URL。如果您还有从该 URL 分支的其他类型的资源,则第二个建议可能不起作用。

另外,我注意到您errorDescriptor使用相同的映射(entityMapping)作为您的successDescriptor. 我不知道这是否是您的意图,但如果您的错误响应应该是一些不同的错误对象,我建议更改它。

希望这可以帮助!

于 2013-05-20T19:29:31.317 回答