如何通过 RestKit 0.20 发布到数据库

Posted

技术标签:

【中文标题】如何通过 RestKit 0.20 发布到数据库【英文标题】:How to Post to database via RestKit 0.20 【发布时间】:2013-06-21 21:47:26 【问题描述】:

我正在尝试使用 restkit 发布到 API。 当我按下保存帖子时,我收到一个错误,显示一个空帖子并警告说:

Expected status code in (200-299), got 422" UserInfo=0xb83ca20 NSLocalizedRecoverySuggestion="body":["can't be blank"], 

帖子显示在 tableView 中,但我输入的文本没有进入数据库。 任何想法为什么会这样?我看到的常见问题是因为人们缺少将数据解析为 json 或者因为他们缺少 responseDescriptor - 但我有这个并且我没有收到 json 错误。它只是不保留我输入的文本。 这是为什么呢?

我的savePost方法是这样的

RKManagedObjectStore *objectStore = [[RKObjectManager sharedManager] managedObjectStore];
Post *post = [NSEntityDescription insertNewObjectForEntityForName:@"Post" inManagedObjectContext:objectStore.mainQueueManagedObjectContext];
[post setBody:self.postTextField.text];
[objectStore.mainQueueManagedObjectContext save:nil];

RKObjectManager *manager = [RKObjectManager sharedManager]; [manager postObject:self path:@"/posts.json" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) 
    NSLog(@"Success saving post");
   // [MUser setCurrentUser:self];
 failure:^(RKObjectRequestOperation *operation, NSError *error) 
    NSLog(@"Failure saving post: %@", error.localizedDescription);
];

在我的 appDelegate 中有这样的设置:

 NSError *error = nil;
    NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"Markofresh" ofType:@"momd"]];
    // 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 *persistentStore = [managedObjectStore addInMemoryPersistentStore:&error];
    NSAssert(persistentStore, @"Failed to add persistent store: %@", error);

    [managedObjectStore createManagedObjectContexts];

    // Configure a managed object cache to ensure we do not create duplicate objects
    managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];

    // Set the default store shared instance
    [RKManagedObjectStore setDefaultStore:managedObjectStore];

    // Configure the object manager
    RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"https://fierce.herokuapp.com"]];
    objectManager.managedObjectStore = managedObjectStore;
    [objectManager setRequestSerializationMIMEType:@"application/json"];
    [objectManager setAcceptHeaderWithMIMEType:@"application/json"];


    [RKObjectManager setSharedManager:objectManager];
    //setup Post Entity map
    RKEntityMapping *entityMapping = [RKEntityMapping mappingForEntityForName:@"Post" inManagedObjectStore:managedObjectStore];
    [entityMapping addAttributeMappingsFromDictionary:@
     @"id":             @"postID",
     @"url":            @"jsonURL",
     @"body":           @"body",
     @"created_at":     @"createdAt"];
    entityMapping.identificationAttributes = @[ @"postID" ];

    [RKObjectManager sharedManager].requestSerializationMIMEType = RKMIMETypeJSON;

    RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:entityMapping pathPattern:@"/posts.json" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

    [objectManager addResponseDescriptor:responseDescriptor];

    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[entityMapping inverseMapping] objectClass:[Post class] rootKeyPath:@"/posts.json"];
    [objectManager addRequestDescriptor:requestDescriptor];

我看到其他人对此很感兴趣,想知道 AFNetworking 是否可能是这种简单方法的更好选择——而且还有更多关于它的文档。 我知道我想做的很简单,我不明白是什么导致了空帖子。任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

你应该这样做:

[manager postObject:post path:@"/posts.json" parameters:nil  ...

所以你的问题只是一个错字?


尝试打开映射跟踪日志,以便查看发生了什么:

RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);

想想Charles Proxy 之类的东西,可以准确地向您展示发生了什么问题。

【讨论】:

无论我有“post”还是“self”似乎都没有区别——我得到了同样的错误。我认为可能是参数为 nil - 我应该像在 rails 中一样为 post 或 body.text 传递一个参数 - 但我还没有找到一种方法来做到这一点,所以我可能走错了路。还有其他想法吗? 所以我已经在 appDelegate 文件中有 RKLogLevelTrace,当我将它复制到 Post 文件时,当它获取数据但来自失败的 POST 的响应相同时,我会得到一个更详细的日志。正如你所说,我得到了 CharlesProxy,我需要一秒钟才能理解它,但我可以看到我有 5 个不完整的请求 - 以为我不确定它们到底有多不完整.. 因此 Charles 允许您详细查看您发送的请求和收到的响应。因此,您可以看到 GET 和 POST 的所有标题和完整正文。您需要清楚地知道服务器期望什么,但它提供了一种验证正在传输的真实数据的方法。

以上是关于如何通过 RestKit 0.20 发布到数据库的主要内容,如果未能解决你的问题,请参考以下文章

从 RestKit 0.10 更新到 0.20

使用 RestKit 0.20 备份核心数据

RestKit 0.20 和 ManagedObjectContexts

如何在 RestKit 0.20 中实现`hasOne:withMapping:`?

你如何在 RestKit 0.20 中使用 RKDotNetDateFormatter?

Restkit 0.20 JSON 映射以及额外的离线数据