具有嵌套项的RestKit动态映射

时间:2016-05-17 16:43:20

标签: ios dynamic nested mapping restkit

我无法为结果数组配置动态映射。我希望映射的结果对象嵌入在"容器中。它描述了所包含对象的类型。

我的JSON类似于以下内容:

"list": {
    "name": ""
    "item_infos": [
    {
        "type": "TaskItem",
        "item": {
            "id": 0
            "title": "A Task Item",
            "task": "..."
        }
        "url": "..."
    },
    {
        "type": "ReminderItem",
        "item": {
            "id": 0
            "title": "A Reminder Item",
            "reminder": "..."
        }
        "url": "..."
    }]
}


我希望将其映射为List对象,其中包含Item个数组,其中每个项目可能属于不同的类型。不同的type是有限且已知的。

class List: NSManagedObject {
    @NSManaged var name: String
    @NSManaged var items: NSOrderedSet
}

class Item: NSManagedObject {
    @NSManaged var identifier: Int32
    @NSManaged var title: String

    // Each mappable `Item` is responsible for providing its own
    // mapping object. It's overridden in the subclasses below.
    class func responseMappingForManagedObjectStore(dos: RKManagedObjectStore) -> RKEntityMapping { ... }
}

class TaskItem: Item {
    @NSManaged var task: String
}

class ReminderItem: Item {
    @NSManaged var reminder: String
}


如何使用item直接在列表下方嵌入RKDynamicMapping,同时仍然使用type字段?我正在尝试沿着这些方向进行响应映射:

let listMapping = RKEntityMapping(forEntityForName: "List", inManagedObjectStore: store)
responseMapping.addAttributeMappingsFromDictionary(["name": "title"])

let dynamicItemMapping = RKDynamicMapping()
dynamicItemMapping.setObjectMappingForRepresentationBlock { representation in

    let itemMapping: RKEntityMapping

    switch representation.valueForKeyPath("type") as? String {
    case .Some("TaskItem"):     itemMapping = TaskItem.responseMappingForManagedObjectStore(objectStore)
    case .Some("ReminderItem"): itemMapping = ReminderItem.responseMappingForManagedObjectStore(objectStore)
    default:                    return nil

    // This is the bit I'm failing to solve. How can I return a mapping
    // that essentially "skips" a level of the JSON, and just maps the
    // embedded `item`, not the `item_info`.
    let itemInfoMapping = RKObjectMapping(forClass: NSMutableDictionary.self)
    itemInfoMapping.addRelationshipMappingWithSourceKeyPath("item", mapping: itemMapping)
    return itemInfoMapping
}

listMapping.addPropertyMapping(RKRelationshipMapping(
    fromKeyPath: "item_infos",
    toKeyPath:   "items",
    withMapping: dynamicItemMapping))

通过此映射,会引发异常:

-[__NSDictionaryM _isKindOfEntity:]: unrecognized selector sent to instance 0x7fd2603cb400

这并不让我感到惊讶,因为设置动态映射的方式无论如何都感觉不对 - 我正在寻找一种方法来跳过"跳过" JSON的级别,仅映射嵌入的item


另一种尝试是将fromKeyPath完全指定为"item_infos.item"listMapping的关系,但之后我无法使用动态映射块中的type字段来确定要使用的Item映射类型:

// ...
dynamicItemMapping.setObjectMappingForRepresentationBlock { representation in
    // `type` inaccessible from the nested item representation
    switch representation.valueForKeyPath("type") as? String {
    case .Some("TaskItem"):     return TaskItem.responseMappingForManagedObjectStore(objectStore)
    case .Some("ReminderItem"): return ReminderItem.responseMappingForManagedObjectStore(objectStore)
    default:                    return nil
}

listMapping.addPropertyMapping(RKRelationshipMapping(
    fromKeyPath: "item_infos.item",
    toKeyPath:   "items",
    withMapping: dynamicItemMapping))

1 个答案:

答案 0 :(得分:1)

您无法完成您尝试做的事情,因为您将核心数据关系连接到包含托管对象的词典数组。

最简单的解决方案是从您所在的位置取出跳过逻辑,并通过在源键(路径)的开头添加item.来创建托管对象(任务和提醒)的所有映射。所以

"item.title" : "title"