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

时间:2015-03-30 19:28:37

标签: ios json swift restkit

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

总结顺序:

  1. JSON数据通过websocket连接进入应用程序
  2. 我使用下面的代码映射它,但没有映射关系
  3. 我使用本地创建的(而不是RestKit)对象与Core Data在同一实体中保存了一些其他记录。
  4. 我从JSON映射的对象现在已经附加了它的关系!
  5. 这是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数据的sqlite数据时,关系列是即使传入的attendeeIdsessionId字段已映射,也会显示空白一旦我在本地进行另一次保存,那么这些关系列就会被映射。

    有什么想法吗?

    编辑: 我应该补充一点,当从一个完整的RestKit调用(如.getObject)或.postObject的结果映射checkin时,映射可以正常工作。只有在我在这里的手动映射中,它似乎才会分崩离析。

1 个答案:

答案 0 :(得分:0)

这是最终的解决方案,其中涉及@wain的大量帮助以及另一篇关于需要使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
}

现在我们将它留在内存缓存中,并且看不到其他人报告的重复项。