RestKit在PUT请求

时间:2015-05-27 15:52:54

标签: ios swift core-data restkit

在以下列方式发出NSInternalInconsistencyException请求时,我的应用与PUT崩溃:

  • 通过HTTP GET
  • 下载个人资料信息
  • 更新客户端上的个人资料
  • 通过HTTP PUT
  • 上传更改
  • 再次解析PUT响应正文的正文

我得到的错误

  

2015-05-27 17:27:17.796 XYZ [17093:2526798] ***由于未捕获的异常而终止应用程序' NSInternalInconsistencyException',原因:'无法使用实体添加对象&# 39;公司'缓存'公司'

的实体

错误来自RKEntityByAttributeCache.m#L333

 NSAssert([entity isKindOfEntity:self.entity], @"Cannot add object with entity '%@' to cache for entity of '%@'", [entity name], [self.entity name]);

现在奇怪的是,entityself.entity对象都具有相同的调试描述。所以我不知道这两个实例的NSEnityDescriptor可能会如何变化。

到目前为止我尝试过的事情

  • 从模拟器中删除应用程序:然后我可以将其更新一次,从那时起我再次收到错误。
  • 删除NSAssert语句:PUT操作现在可以正常运行。
  • 按照here 所述禁用缓存(在Restkit 0.24.1中,这似乎不再可能)

我的映射

我确实将我的映射实现为RKManagedObjectStore的扩展,如下所示:

extension RKManagedObjectStore{
    var companyMapping: RKEntityMapping{
        let mapping = RKEntityMapping(
            forEntityForName: "Company",
            inManagedObjectStore: self
        )
        mapping.addAttributeMappingsFromArray(
            ["id", "name"]
        )
        mapping.identificationAttributes = ["id"]

        return mapping
    }

    var profileMapping: RKEntityMapping{
        let mapping = RKEntityMapping(
            forEntityForName: "Profile",
            inManagedObjectStore: self
        )
        mapping.addAttributeMappingsFromArray(
            ["id", "content", "language", "profileImageId" ]
        )
        mapping.identificationAttributes = ["id"]
        mapping.addRelationshipMappingWithSourceKeyPath("companies", mapping: companyMapping)

        return mapping
    }
}

数据我发布到服务器并以相同的格式返回响应:

{
    "content": "XYZ",
    "id": "profile-1",
    "language": "de",
    "companies": [{
        "id": "company-1",
        "name": "Somecompany Inc."
    }]
}

更新NSMangedObectContext

由于该问题似乎与多个NSManagedObjectContext有关,因此以下是我设置RestKit和MOC的方法:

init(baseURL: String, dataModelName: String){

    let modelURL = NSBundle.mainBundle().URLForResource(dataModelName, withExtension: "momd")!
    let managedObjectModel = NSManagedObjectModel(contentsOfURL: modelURL)!
    self.managedObjectStore = RKManagedObjectStore(managedObjectModel: managedObjectModel)

    let storePath = RKApplicationDataDirectory().stringByAppendingPathComponent("\(dataModelName).sqlite")

    var error: NSError? = nil
    managedObjectStore.addSQLitePersistentStoreAtPath(storePath,
        fromSeedDatabaseAtPath: nil,
        withConfiguration: nil,
        options: nil,
        error: &error
    )
    if let e = error{
        // Omitted: Delete the SQLite store and re-create it
    }
    managedObjectStore.createManagedObjectContexts()
    managedObjectStore.managedObjectCache = RKInMemoryManagedObjectCache(
        managedObjectContext: managedObjectStore.persistentStoreManagedObjectContext
    )
    objectManager = RKObjectManager(baseURL: NSURL(string: baseURL))
    objectManager.managedObjectStore = managedObjectStore
    objectManager.requestSerializationMIMEType = RKMIMETypeJSON;

    super.init(baseURL: baseURL)

    setupMapping()
}

2 个答案:

答案 0 :(得分:1)

  

现在奇怪的是,实体和self.entity对象都具有相同的调试描述。

实体描述的地址必须不同。

当您篡改RestKit正在使用的托管对象上下文时,通常会发生这种情况,因此被比较的实体来自2个不同的上下文,因此不同,或者直接从错误的上下文传递托管对象。

答案 1 :(得分:0)

您必须创建ManagedObjectStore。我怀疑self作为参数是正确的。我从你的解释中推断出self是NSManagedObject的子类,即你要映射的实体,CompanyProfile但是你需要RKManagedObjectStore并将其作为第二个参数传递。< / p>

let mapping = RKEntityMapping(
    forEntityForName: "Profile",
    inManagedObjectStore: <pointer to the RKManagedObjectStore>
)