【问题标题】:RealmSwift + ObjectMapper managing String Array (tags)RealmSwift + ObjectMapper 管理字符串数组(标签)
【发布时间】:2016-10-16 17:27:35
【问题描述】:

我需要在 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

【问题讨论】:

  • MyTagObject 类是什么样的?
  • 我用 ozgur 类更新了问题
  • 我不知道是什么问题。 tag 是“MyTagbject”的列表,所以这应该可以正常工作...

标签: swift realm objectmapper


【解决方案1】:

我的解决方案是使用 ObjectMapper TransformType 作为自定义方法将 JSON 映射到 Realm List&lt;String&gt; 类型。不需要 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 &lt;- (map["tags"], StringArrayTransform())。这告诉 ObjectMapper 使用我们在上面展示的自定义 StringArrayTransform,它采用 JSON 字符串数组并将其转换为领域 List&lt;String&gt;

【讨论】:

    【解决方案2】:

    首先我们应该假设我们的模型同时扩展了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 中。

    【讨论】:

      【解决方案3】:

      如果您的标签数组包含带有键的 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)
      }
      

      【讨论】:

      • 没错!!格式无法更改,那么我该如何编码呢?有例子吗?
      • for tagName in tags { let tagObject = MyTagObject() tagObject.name = tagName myObject.tags.append(tagObject) }
      • 我假设它在映射函数内部,但是如何在你的 for 循环示例中获取“标签”?
      • 使用解析库。喜欢 SwiftyJSON
      • 哦,你的意思是根本不使用 ObjectMapper...编写我自己的自定义解析。
      【解决方案4】:

      关注此代码

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-08-17
        • 2021-07-28
        • 1970-01-01
        • 1970-01-01
        • 2023-03-31
        • 1970-01-01
        • 2021-11-27
        相关资源
        最近更新 更多