swift中字串型資料對映為數值型資料的解決辦法

weixin_34326429發表於2016-10-12

一條json資料,全部是字串型別的,如

{
      navi_radio = "2.10"
      price = "10"
      price_radio = "-0.28"
      ...
      diff = "--"  
}

這一條json實際上包含數值型的字串傳資料和以及真正的字串,如果全在對映時全部轉換為數值型(Double ,Int之類的),那麼會有crash的情況,因為有些並不是數值型,而是真正的字串,而且在全部設定為數值型的時候,對映出來的值也不對,全部為nil,因為資料型別不對,objectMapper對映的結構與後臺返回的json資料結構是一致的,後臺返回什麼樣的資料型別,就只能用什麼樣的資料型別欄位解析,否則沒有結果。我用的是realmSwift 進行儲存,發現realmSwift對這種數值型字串排序的支援並不好,存在排序不準確的情況(而且是一定會發生的情況),對映框架我用的是 objectMapper,在處理這個問題上,在realm-cocoa的issue上請教了作者,最後找到了解決辦法
objectMapper提供了一種轉換機制,在對映的時候就可以進行轉換,


class Model: Object, Mappable {
  dynamic var navi_radio = ""       
  dynamic var price = "" 
  dynamic var price_radio = ""   
//   這裡必須是對應的字串型別,雖然知道它是數值型的,
//   如果強制轉換為 dynamic var price = 0.00 這樣的資料,結果為nil
  required convenience init?(_ map: Map) {
             self.init() 
       } 
   
func mapping(map: Map) { 
          navi_radio <- map["navi_radio"] 
          price <- map["price"] 
          price_radio <- map["price_radio"] 
          ...
          diff <- map["diff"] 
    }
}
// 這是基本的對映結構,如果僅僅是這樣,是解決不了問題的.

那麼就需要用下面的方法來進行轉換了。

class Model: Object, Mappable {
  dynamic var navi_radio = ""       
  dynamic var price = "" 
  dynamic var price_radio = ""   
//   這裡必須是對應的字串型別,雖然知道它是數值型的,
//   如果強制轉換為 dynamic var price = 0.00 這樣的資料,結果為nil
  required convenience init?(_ map: Map) {
             self.init() 
       } 
   
// 將String轉換為為Double型 - 進行對映
let transformDouble = TransformOf<Double, String>(fromJSON: { (value: String?) -> Double? in 
          // transform value from String? to Double? 
          return Double(value!)
}, toJSON: { (value: Double?) -> String? in 
          // transform value from Double? to String?
         if let value = value { 
                return String(value) 
          }
           return nil
      })

// 將String轉換為Int進行對映
let transformInt = TransformOf<Int, String>(fromJSON: { (value: String?) -> Int? in 
          // transform value from String? to Int? 
          return Int(value!)
}, toJSON: { (value: Int?) -> String? in 
          // transform value from Int? to String?
         if let value = value { 
                return String(value) 
          }
           return nil
      })

// 對映結構
func mapping(map: Map) { 
          navi_radio <-(map["navi_radio"],transformDouble) 
          price <- (map["price"] ,transformInt)
          price_radio <- (map["price_radio"] ,transformDouble)
          ...
          diff <- map["diff"] 
    }
}

if let value = value { 
                return String(value) 
         }
           return nil
在這裡原路返回就行,根據你的喜好返回對應的空值就OK了

對映時呼叫上面的轉換方法,哪個欄位需要轉換,就用哪個欄位呼叫對應的方法
此外,這個方法可以寫多個,
比如現在這上面可以寫Double型的轉換,同時還可以寫Int型的轉換,等等...
至於diff = "--"這樣的其實表示的沒值的情況,返回的是 "--",那麼遇到"--"這的情況下會走下面這句程式碼
轉換為數值型後,排序就準確了。

相關文章