RealmSwift + ObjectMapper管理字符串数组(标签)

时间:2016-10-16 17:27:35

标签: swift realm objectmapper

我需要在RealmSwift中表示的是以下JSON方案:

{ 
    "id": 1234,
    "title": "some value",
    "tags": [ "red", "blue", "green" ]
}

它是一个我磕磕绊绊的基本字符串数组。我在Realm中猜测我需要将“标签”表示为

dynamic id: Int = 0
dynamic title: String = ""
let tags = List<MyTagObject>()

在Realm中制作标签自己的表,但是如何使用ObjectMapper映射它?这是我有多远......

func mapping(map: Map) {
    id <- map["id"]
    title <- map["title"]
    tags <- map["tags"]
}

...但是标签行当然没有编译,因为List和Realm不能使用[String]类型。

这感觉像是一个有点常见的问题,我希望有人能够面对这个问题,可以评论或指向一个有建议的帖子。

更新1 MyTagObject如下所示:

class MyTagObject: Object {
    dynamic var name: String = ""
}

更新2 我发现这个帖子处理领域对象,但假设数组有命名元素而不是简单字符串。 https://gist.github.com/Jerrot/fe233a94c5427a4ec29b

4 个答案:

答案 0 :(得分:3)

首先,我们应该假设我们的模型同时扩展了ObjectMappable

让我们创建一个包装器模型来存储基元(String)类型:

class StringObject: Object {
    dynamic var value = ""
}

然后我们描述了根模型(而不是包装器)的相应属性和映射规则:

var tags = List<StringObject>()

var parsedTags: [String] {
    var result = [String]()
    for tag in tags {
        result.append(tag.value)
    }
    return result
}

override static func ignoredProperties() -> [String] {
    return ["parsedTags"]
}

func mapping(map: Map) {
    if let unwrappedTags = map.JSON["tags"] as? [String] {
        for tag in unwrappedTags {
            let tagObject = StringObject()
            tagObject.value = tag
            tags.append(tagObject)
        }
    }
}

我们需要一个tags属性来存储和获取有关Realm标签的数据。 然后parsedTags属性简化了通常数组格式的标记提取。 ignoredProperties定义允许在节省数据的同时避免Realm的一些失败(因为我们当然不能在Realm中存储非Realm数据类型)。 最后,我们手动解析mapping函数中的标签,将其存储在Realm中。

答案 1 :(得分:1)

如果您的tags数组包含带有键的Dictionary对象:“name”

,它将起作用
{ 
    "id": 1234,
    "title": "some value",
    "tags": [ ["name" : "red"], ... ]
}

如果您无法修改JSON对象,我建议您以编程方式将json映射到域。

for tagName in tags {
    let tagObject = MyTagObject()
    tagObject.name = tagName
    myObject.tags.append(tagObject)
}

答案 2 :(得分:1)

我的解决方案是使用ObjectMapper TransformType作为自定义方法,将JSON映射到Realm List<String>类型。无需2个Realm模型。

使用示例JSON:

{ 
    "id": 1234,
    "title": "some value",
    "tags": [ "red", "blue", "green" ]
}
  1. 首先,创建一个ObjectMapper TransformType对象:
import Foundation
import ObjectMapper
import RealmSwift

public struct StringArrayTransform: TransformType {

    public init() { }

    public typealias Object = List<String>
    public typealias JSON = [String]

    public func transformFromJSON(_ value: Any?) -> List<String>? {
        guard let value = value else {
            return nil
        }
        let objects = value as! [String] 
        let list = List<String>()
        list.append(objectsIn: objects)
        return list
    }

    public func transformToJSON(_ value: Object?) -> JSON? {
        return value?.toArray()
    }

}

  1. 创建用于存储JSON数据的1 Realm模型:
import Foundation
import RealmSwift
import ObjectMapper

class MyObjectModel: Object, Mappable {

    @objc dynamic id: Int = 0
    @objc dynamic title: String = ""
    let tags = List<MyTagObject>()

    required convenience init?(map: Map) {
        self.init()
    }    

    func mapping(map: Map) {
        id <- map["id"]
        title <- map["title"]
        tags <- (map["tags"], StringArrayTransform())
    }

}

完成!

这行很神奇:tags <- (map["tags"], StringArrayTransform())。这告诉ObjectMapper使用我们在上面显示的自定义StringArrayTransform,它使用JSON String数组并将其转换为领域List<String>

答案 3 :(得分:0)

遵循此代码

import ObjectMapper
import RealmSwift

//Create a Model Class
class RSRestaurants:Object, Mappable {

    @objc dynamic var status: String?
    var data = List<RSData>()
    
    required convenience init?(map: Map) {
        self.init()
    }
    
    func mapping(map: Map) {
        status <- map["status"]
        data <- (map["data"], ListTransform<RSData>())
    }
}

//Use this for creating Array
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
    }
}