Alamofire,Objectmapper,Realm:嵌套对象

时间:2015-11-19 12:37:02

标签: swift realm alamofire objectmapper

我正在使用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中的映射功能永远不会被调用。

4 个答案:

答案 0 :(得分:4)

旧的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"]
    }
}

答案 1 :(得分:3)

您遇到的问题是由于ObjectMapper不了解Realm的List类型。它不知道它是一个集合类型,它必须在适当的位置进行变异而不是被分配。您可以在ObjectMapper GitHub issue #143中看到对此的讨论,包括一些建议的解决方法。

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

答案 2 :(得分:3)

qs = Article.objects.all()
qs = qs.extra(select = {
    'recent_comments': """
    SELECT
        json_build_object('comments',
            array_agg(
              json_build_object('id', id, 'user_id', user_id, 'body', body)
            )
        )
    FROM (
        SELECT
          c.id,
          c.user_id,
          c.body
        FROM app_comment c
        WHERE c.article_id = app_article.id
        ORDER BY c.id DESC
        LIMIT 3
    ) sub
    """
})

for article in qs:
    print(article.recent_comments)

# Output:
# {u'comments': [{u'user_id': 1, u'id': 3, u'body': u'foo'}, {u'user_id': 1, u'id': 2, u'body': u'bar'}, {u'user_id': 1, u'id': 1, u'body': u'joe'}]}
# ....

然后在你的模型中这样的事情。

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
    }
}

答案 3 :(得分:-1)

您可以使用像:

这样的运算符函数扩展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