如何将 PUT 请求添加到 RestKit + Core Data?

Posted

技术标签:

【中文标题】如何将 PUT 请求添加到 RestKit + Core Data?【英文标题】:How do I add PUT requests to RestKit + Core Data? 【发布时间】:2014-01-15 14:13:15 【问题描述】:

按照 RKGist 示例应用程序,我设法通过 RestKit 使我的 API 与 Core Data 同步。

这仅适用于具有关联的一个模型;我正在尝试添加额外的路线,但无法正常工作。

AppDelegate.m

- (void)setupRestKit

    // ...
    RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[JGMappingProvider personMapping]
                                                                                            method:RKRequestMethodGET
                                                                                       pathPattern:@"people"
                                                                                           keyPath:@"response"
                                                                                       statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

    [objectManager addResponseDescriptor:responseDescriptor];



    responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[JGMappingProvider companyMapping]
                                                                      method:RKRequestMethodGET
                                                                 pathPattern:@"companies"
                                                                     keyPath:@"response"
                                                                 statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

    [objectManager addResponseDescriptor:responseDescriptor];


    // add some routes
    [[RKObjectManager sharedManager].router.routeSet addRoute:[RKRoute routeWithName:@"approve_company" pathPattern:@"companies/:companyId/approve" method:RKRequestMethodPUT]];

    ...

JGMappingProvider.m

+ (RKMapping *)companyMapping

    RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Company"
                                                          inManagedObjectStore:[[RKObjectManager sharedManager] managedObjectStore]];

    [mapping addAttributeMappingsFromDictionary:@
                                                         @"id":             @"companyId",
                                                         @"name":           @"name",
                                                         @"looking_for":    @"lookingFor",
                                                         @"location":       @"location",
                                                         @"updated_at":     @"updatedAt",
                                                         @"created_at":     @"createdAt"];

    mapping.identificationAttributes = @[ @"companyId" ];

    [mapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"person" toKeyPath:@"person" withMapping:[self personMapping]]];

    return mapping;



+ (RKMapping *)personMapping

    RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Person"
                                                         inManagedObjectStore:[[RKObjectManager sharedManager] managedObjectStore]];


    [mapping addAttributeMappingsFromDictionary:@
                                                        @"name":           @"name",
                                                        @"nickname":       @"nickname",
                                                        @"id":             @"personId",
                                                        @"email":          @"email"];

    mapping.identificationAttributes = @[ @"personId" ];

    return mapping;


@end

这一切都很好。但是,当我尝试添加一些额外的路线时……

ViewController.m

- (void)approve

    NSMutableURLRequest *request = [[RKObjectManager sharedManager] requestWithPathForRouteNamed:@"approve_company" object:_company parameters:nil];
    [self sendRequestWithSharedManager:request];


- (void)reject

    NSMutableURLRequest *request = [[RKObjectManager sharedManager] requestWithPathForRouteNamed:@"reject_company" object:_company parameters:nil];
    [self sendRequestWithSharedManager:request];


- (void)sendRequestWithSharedManager:(NSMutableURLRequest *)request 
    RKObjectRequestOperation* operation = [[RKObjectManager sharedManager] objectRequestOperationWithRequest:(NSURLRequest *)request success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) 
        NSLog(@"success!");
     failure:^(RKObjectRequestOperation *operation, NSError *error) 
        NSLog(@"%@", [error description]);
    ];


    operation.targetObject = nil; // this was suggested in a tutorial, has no affect

    NSLog(@"Requested %@", [operation.HTTPRequestOperation.request.URL description]); // this is the correct URL, all the time

    [[RKObjectManager sharedManager] enqueueObjectRequestOperation:operation];

大多数时候它都失败了。具体来说,前两个请求似乎失败了——根本没有访问我的服务器(我在服务器端有一些断点要调试),但在第三个请求上它运行良好。

我很困惑 - 如果它第三次工作,那么大概是设置了一些东西吧?

这里是日志 - 它们有点乱,我真的不知道我在寻找什么。 https://gist.github.com/jongd/d28b5f58a901270999f2/raw/839f1b529538ab1814a49350c33b0057cb5b98fc/logger.txt

啊哈 - 原来 /was/ 击中了我的服务器,日志是错误的。小学生的错误 - 对此感到抱歉。

我的响应描述符仍然设置不正确 - 我可以得到一些帮助吗?

[RKResponseDescriptor responseDescriptorWithMapping:[JGMappingProvider companyMapping]
                                             method:RKRequestMethodPUT
                                        pathPattern:@"companies/:companyId/approve"
                                            keyPath:@"response"
                                        statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

我似乎无法让 pathPattern 匹配 - 理想情况下,我会有一个匹配 Companies/:companyId/approve & Companies/:companyId/reject 的通配符,但我看不到如何在文档。

为愚蠢的问题道歉!

编辑:完成!我正在使用 responseDescriptorWithMapping: method: pathPattern: keyPath: statusCodes: - 一切都与(已弃用?) responseDescriptorWithMapping: pathPattern: keyPath: statusCodes:

【问题讨论】:

【参考方案1】:

首先,您确定您没有访问服务器 - 根据您的日志,它似乎到达了服务器:

'http://localhost:1313/api/1/companies/19/approve' (200 OK / 0 objects) [request=1.0492s mapping=0.0000s total=1.0514s]

您的第二个 RKResponseDescriptor(用于公司的)似乎存在问题。

您能否尝试不重用局部变量 responseDescriptor 来创建和传递第二个 RKResponseDescriptor。

【讨论】:

啊,我需要每个 RKRoute 的 RKResponseDescriptor 吗?我认为它会选择现有的一个。 (谢谢 - 将三重检查它没有访问我的服务器 - 也许我做了一些愚蠢的事情;)) 您需要至少为每种不同类型的映射以及可能为每个路径/路由定义一个 RKResponseDescriptor(但您可以在此处使用通配符以最大限度地减少必要定义的数量) 响应描述符定义和注册很好,问题是那些响应描述符指定的路径模式(与路由路径模式相比)。【参考方案2】:

我假设您的基本 URL 是 http://localhost:1313/api/1/

您的所有 3 个请求都有一个 URL:'http://localhost:1313/api/1/companies/19/approve'RestKit logs "No response descriptors match the response loaded."。这意味着在所有响应描述符中,没有一个路径模式与companies/19/approve 匹配。你需要一个能做到的。

第 3 个请求没有成功映射任何映射...虽然所有 3 个请求都到达了服务器(您可以在日志中看到响应内容。

请记住,路由用于创建请求路径。通常是通过属性注入(因此注入了19 的路径companies/19/approve)。

响应描述符仅通过使用请求路径模式才链接到路由。每当您发出请求时,您都需要一个与该请求匹配的响应描述符。 (nil 的响应描述符路径模式匹配所有内容)。

【讨论】:

啊,谢谢 - 现在有地方了。我已经用更多信息和代码更新了问题的结尾;你能再看看吗? :) 不使用method:参数意味着它匹配所有请求类型。服务器实际上是在接收PUT 还是GET?我希望请求是PUT,但我不能说我实际上已经尝试过与您的代码完全一样的代码。

以上是关于如何将 PUT 请求添加到 RestKit + Core Data?的主要内容,如果未能解决你的问题,请参考以下文章

Restkit如何将任意json(键可能会超时更改)映射到NSDictionary

RestKit 在 PUT 请求时抛出 NSInternalInconsistencyException

使用 RESTkit PUT 请求、更改标头并将响应保存在核心数据中

Restkit 将多个 json 提要映射到同一个数组

带有 RestKit 0.10.1 和简单返回类型的 HTTP PUT

Restkit:将请求中的字段包含到对象映射中