RestKit 在 PUT 请求时抛出 NSInternalInconsistencyException
RestKit throws NSInternalInconsistencyException upon PUT request
当按以下方式发出 PUT
请求时,我的应用程序因 NSInternalInconsistencyException
而崩溃:
- 通过
HTTP GET
下载个人资料信息
- 更新客户端上的配置文件
- 通过
HTTP PUT
上传更改
- 再次解析
PUT
响应正文的正文
我得到的错误
2015-05-27 17:27:17.796 XYZ[17093:2526798] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Cannot add object with entity 'Company' to cache for entity of 'Company''
错误来自这里RKEntityByAttributeCache.m#L333:
NSAssert([entity isKindOfEntity:self.entity], @"Cannot add object with entity '%@' to cache for entity of '%@'", [entity name], [self.entity name]);
奇怪的是,entity
和 self.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
}
}
数据 I post 到服务器并以相同的格式返回响应:
{
"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()
}
您必须创建一个 ManagedObjectStore。我怀疑 self
作为参数是否正确。我从你的解释中推断出 self 是 NSManagedObject 的子类,即你想要映射的实体,Company
或 Profile
但是你需要一个 RKManagedObjectStore
并将其作为第二个参数传递。
let mapping = RKEntityMapping(
forEntityForName: "Profile",
inManagedObjectStore: <pointer to the RKManagedObjectStore>
)
Curiously now, the entity and the self.entity object both have the same debug description.
实体描述的地址必须不同。
当您篡改 RestKit 使用的托管对象上下文时,通常会发生这种情况,因此比较的实体来自 2 个不同的上下文,因此是不同的,或者当您直接从错误的上下文传递托管对象时。
当按以下方式发出 PUT
请求时,我的应用程序因 NSInternalInconsistencyException
而崩溃:
- 通过
HTTP GET
下载个人资料信息
- 更新客户端上的配置文件
- 通过
HTTP PUT
上传更改 - 再次解析
PUT
响应正文的正文
我得到的错误
2015-05-27 17:27:17.796 XYZ[17093:2526798] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Cannot add object with entity 'Company' to cache for entity of 'Company''
错误来自这里RKEntityByAttributeCache.m#L333:
NSAssert([entity isKindOfEntity:self.entity], @"Cannot add object with entity '%@' to cache for entity of '%@'", [entity name], [self.entity name]);
奇怪的是,entity
和 self.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
}
}
数据 I post 到服务器并以相同的格式返回响应:
{
"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()
}
您必须创建一个 ManagedObjectStore。我怀疑 self
作为参数是否正确。我从你的解释中推断出 self 是 NSManagedObject 的子类,即你想要映射的实体,Company
或 Profile
但是你需要一个 RKManagedObjectStore
并将其作为第二个参数传递。
let mapping = RKEntityMapping(
forEntityForName: "Profile",
inManagedObjectStore: <pointer to the RKManagedObjectStore>
)
Curiously now, the entity and the self.entity object both have the same debug description.
实体描述的地址必须不同。
当您篡改 RestKit 使用的托管对象上下文时,通常会发生这种情况,因此比较的实体来自 2 个不同的上下文,因此是不同的,或者当您直接从错误的上下文传递托管对象时。