Alamofire,Objectmapper,Realm:嵌套对象

Posted

技术标签:

【中文标题】Alamofire,Objectmapper,Realm:嵌套对象【英文标题】:Alamofire, Objectmapper, Realm: Nested Objects 【发布时间】:2016-02-21 14:42:11 【问题描述】:

我正在使用 Alamofire、Objectmapper、Realm,除了一件事之外,一切都在工作:我无法映射嵌套对象。

class Voting: Object, Mappable 

    dynamic var votingID: String = ""
    dynamic var question: String = ""
    var votingOptions = List<VotingOption>()

    required convenience init?(_ map: Map) 
        self.init()
    

    func mapping(map: Map) 
        votingID <- map["id"]
        question <- map["question"]
        votingOptions <- map["votingOptions"]
    

    override class func primaryKey() -> String 
        return "votingID"
       


class VotingOption: Object, Mappable

    dynamic var optionID: String = ""
    dynamic var text: String = ""


    required convenience init?(_ map: Map) 
        self.init()
    

    func mapping(map: Map) 
        optionID <- map["id"]
        text <- map["optionText"]
    

    override class func primaryKey() -> String 
        return "optionID"
       

我要映射的 JSON 是:


    "Voting": [
        
            "question": "Which option do yo prefer?",
            "id": "7f073efd-6f3d-43f2-9fe4-5cad683b77a2",
            "votingOptions": [
                
                    "optionText": "Option 3",
                    "id": "3bc0a618-8791-4862-a7fd-5f2df464697d"
                ,
                
                    "optionText": "Option 1",
                    "id": "84c6a830-814b-40c8-a252-c074be5d689a"
                ,
                
                    "optionText": "Option 2",
                    "id": "8872ef6f-fc70-445a-802e-d39944006467"
                
            ]
        
    ]

VotingOption 中的映射函数永远不会被调用。

【问题讨论】:

【参考方案1】:

旧的ListTransform 解决方案不再适用于 Swift 3。

这就是我现在使用的;例如,将其放入名为ListExtensions.swift 的文件中。

import Foundation
import ObjectMapper
import RealmSwift

/// Maps object of Realm's List type
func <- <T: Mappable>(left: List<T>, right: Map)

    var array: [T]?

    if right.mappingType == .toJSON 
        array = Array(left)
    

    array <- right

    if right.mappingType == .fromJSON 
        if let theArray = array 
            left.append(objectsIn: theArray)
        
    

这使您可以像这样简单地使用它:

class Parent: Object, Mappable 
    dynamic var id: Int = 0
    var children = List<Child>()

    required convenience init?(_ map: Map) 
        self.init()
    

    func mapping(map: Map) 
        id <- map["id"]
        children <- map["children"]
    

【讨论】:

也面临这个问题。您的解决方案有帮助!你是救生员,谢谢!【参考方案2】:

您看到的问题是由于 ObjectMapper 不了解 Realm 的 List 类型。它不知道它是一个集合类型,并且它必须就地变异而不是分配给它。您可以在 ObjectMapper GitHub issue #143 中查看对此的讨论,包括一些建议的解决方法。

另请注意,Object 子类上的任何List 属性都应使用let 而不是var 声明。

【讨论】:

【参考方案3】:
class ListTransform<T:RealmSwift.Object> : TransformType where T:Mappable 
    typealias Object = List<T>
    typealias JSON = [AnyObject]

    let mapper = Mapper<T>()

    func transformFromJSON(_ value: Any?) -> Object? 
        let results = List<T>()
        if let objects = mapper.mapArray(JSONObject: value) 
            for object in objects 
                results.append(object)
            
        
        return results
    

    func transformToJSON(_ value: Object?) -> JSON? 
        var results = [AnyObject]()
        if let value = value 
            for obj in value 
                let json = mapper.toJSON(obj)
                results.append(json as AnyObject)
            
        
        return results
    

然后在你的模型中是这样的。

class Parent: Object, Mappable 
    dynamic var id: Int = 0
    var children = List<Child>()

    required convenience init?(_ map: Map) 
        self.init()
    

    func mapping(map: Map) 
        id <- map["id"]
        child <- (map["children"], ListTransform<Child>())
    

【讨论】:

谢谢,我已重用您的代码将 dict 解析为对象数组,其中 object 的字段包含该对象的 dict 中的键。 试用当前版本【参考方案4】:

您可以为 Realm.List 类型扩展 ObjectMapper,使用如下运算符函数:

public func <- <T: Object where T: Mappable, T: JSPrimaryKey>(left: List<T>, right: Map) 
  if right.mappingType == MappingType.FromJSON 
    if let value = right.currentValue 
      left.removeAll()
      if let json = value as? [[String : AnyObject]] 
        let objs = RealmS().add(T.self, json: json)
        left.appendContentsOf(objs)
      
    
  

自己试试吧。

ObjectMappper + Realm List type

【讨论】:

以上是关于Alamofire,Objectmapper,Realm:嵌套对象的主要内容,如果未能解决你的问题,请参考以下文章

Swift 3 的 ObjectMapper 和 Alamofire 问题 Alamofire 4 的 Alamofire 版本

Swift/Alamofire/ObjectMapper:忽略零值

AlamoFire + ObjectMapper,如何让函数获取 Mappable 类型的参数?

如何使用 AlamoFire/ObjectMapper 访问嵌入在 JSON 字典中的链接?

Alamofire +ObjectMapper模型: 上传音频。

使用 ObjectMapper 和 Alamofire 时对象始终为零