手动映射 JSON 对象时 RestKit 关系不映射

RestKit relationships not mapping when manually mapping JSON object

我正在关注一些关于如何使用 RKMapperOperation 直接映射传入 JSON 数据的建议帖子。我的实体对象正在数据存储中创建,但没有正确的关系。有趣的是,如果我在映射传入 JSON(通过 websockets)后直接使用 Core Data 方法创建一个对象,该操作似乎 "flesh" 排除了我在不正确实体中的关系。

求和顺序:

  1. JSON 数据通过 websocket 连接进入应用程序
  2. 我使用以下代码映射它,但未映射关系
  3. 我使用带有 Core Data 的本地创建(不是 RestKit)对象在同一个实体中保存一些其他记录。
  4. 从 JSON 映射的我的对象现在附加了它的关系!

这是 JSON 数据:

{
    "checkin": {
        "session_id": 1,
        "attendee_id": 70,
        "source": "list",
        "created_at": "2015-03-26 11:53:08",
        "cache_id": "9234d700852df5c7402b87adf6ecfc19",
        "checkout": "0",
        "updated_at": "2015-03-27 03:53:09",
        "id": 359
    }
}

这是我的映射函数

func mapEntityFromJson(JSONString: String, key: String, mapping: RKEntityMapping!) -> NSManagedObject? {
    let MIMEType = "application/json"
    var error: NSError? = nil
    let data = JSONString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
    let jsonDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary
    let parsedData: AnyObject! = RKMIMETypeSerialization.objectFromData(data, MIMEType: MIMEType, error: &error)
    if (parsedData == nil && error != nil) {
        // Parser error...
        return nil
    }

    let mappingsDictionary = [ key: mapping ]

    let mappingDS = RKManagedObjectMappingOperationDataSource(managedObjectContext: self.objectStore.persistentStoreManagedObjectContext, cache: self.objectStore.managedObjectCache)

    let mapper = RKMapperOperation(representation: parsedData, mappingsDictionary: mappingsDictionary)
    mapper.mappingOperationDataSource = mappingDS
    var mappingError: NSError? = nil
    let isMapped = mapper.execute(&mappingError)
    if (isMapped && mappingError == nil) {
        // Trying to save twice per some other example
        self.objectStore.persistentStoreManagedObjectContext.save(&error)
        self.objectStore.persistentStoreManagedObjectContext.saveToPersistentStore(&error)
        let result = mapper.mappingResult.firstObject() as NSManagedObject
                    return result
    }
    return nil
}

这是我传递给此函数的关系映射:

func checkinMapping() -> RKEntityMapping {
    let checkinMapping = RKEntityMapping(forEntityForName: "Checkin", inManagedObjectStore: objectStore)
    let checkinDictionary = ["source": "source", "checkout": "checkout", "cache_id": "cacheId", "attendee_id": "attendeeId", "session_id": "sessionId"]

    checkinMapping.addAttributeMappingsFromDictionary(baseRecordDictionary)
    checkinMapping.addAttributeMappingsFromDictionary(checkinDictionary)
    checkinMapping.addConnectionForRelationship("attendee", connectedBy: ["attendeeId": "id"])
    checkinMapping.addConnectionForRelationship("session", connectedBy: ["sessionId": "id"])
    checkinMapping.identificationAttributes = ["cacheId"]
    checkinMapping.setDefaultValueForMissingAttributes = true

    return checkinMapping
}

以下是通知 websocket 订阅时如何调用函数:

let jsonString = "<the JSON data per above>"
let mappingResult = self.mapEntityFromJson(jsonString, key: "checkin", mapping: self.checkinMapping())

attendee_idsession_id 值应该与 AttendeeSession 实体建立关系,但是当我查看 Core Data 底层的 sqlite 数据时,关系即使传入的 attendeeIdsessionId 字段被映射,列也是空白的。一旦我将另一个保存在本地,那么这些关系列就会被映射。

有什么想法吗?

编辑: 我应该补充一点,当签入是从完整的 RestKit 调用(如 .getObject)或作为 .postObject 的结果映射时,映射工作没有问题。只是在我这里的手动映射中,它似乎崩溃了。

这是最终的解决方案,其中涉及@wain 的大量帮助和另一个 post 的关键点,即需要让 operationQueue 等待所有操作完成,否则映射过程尚未完成映射关系。所以我的 NSManagedObject 返回时没有连接任何关系。用于正确并发和保存数据的私有子上下文的组合以及等待问题解决了这个问题。这是最终的映射代码:

func mapEntityFromJson(JSONString: String, key: String, mapping: RKEntityMapping!) -> NSManagedObject? {
    let MIMEType = "application/json"
    var error: NSError? = nil
    let data = JSONString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
    let jsonDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary
    let parsedData: AnyObject! = RKMIMETypeSerialization.objectFromData(data, MIMEType: MIMEType, error: &error)
    if (parsedData == nil && error != nil) {
        // Parser error...
        return nil
    }

    let mapperContext = self.objectStore.newChildManagedObjectContextWithConcurrencyType(NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType, tracksChanges: true)

    let mappingsDictionary = [ key: mapping ]

    let mappingDS = RKManagedObjectMappingOperationDataSource(managedObjectContext: mapperContext, cache: self.objectStore.managedObjectCache)
    var mappingResult: RKMappingResult? = nil
    var result: NSManagedObject? = nil

    let mapper = RKMapperOperation(representation: parsedData, mappingsDictionary: mappingsDictionary)
    mappingDS.operationQueue = self.operationQueue
    mappingDS.parentOperation = mapper
    mapper.mappingOperationDataSource = mappingDS
    var mappingError: NSError? = nil
    let isMapped = mapper.execute(&mappingError)
    // Necessary to wait for relationships to map.
    if self.operationQueue!.operationCount > 0 {
        self.operationQueue!.waitUntilAllOperationsAreFinished()
    }
    if (isMapped && mappingError == nil) {
        mapperContext.saveToPersistentStore(&error)
        mappingResult = mapper.mappingResult
    }

    if mappingResult != nil {
        result = mappingResult!.firstObject() as? NSManagedObject
    }

    return result
}

现在我们将其保留在内存缓存中,不会看到其他人报告的重复问题。