2個關鍵點:一個是讀取、一個是寫入,
顯示界面:讀取結構體的欄位名,欄位型別,即可判斷、顯示相應的UI控制元件;
用戶寫入資料:需要知道每個UI控制元件和哪個欄位進行系結,另外,對欄位需要有寫的權限,
嘗試Mirror【失敗】
第一個嘗試的方案是運用反射技術,在Swift中,使用的是Mirror,Mirror可以讀取結構體的屬性,但不能修改結構體,
嘗試Dictionary【失敗】
第二個嘗試的方案是使用字典Dictionary
具體步驟是:
- 初始化結構體
- 通過JSONSerialization序列化成字典
- 遍歷字典顯示界面,,,[卡住]
單單是在讀取這里,就遇到一個棘手的問題,Swift是強型別的語言,所以讀取Dictionary的嵌套欄位,需要一長串的型別轉換,這就很難寫出簡潔易懂的代碼,
比如:
var dic:[String: Any] = ["a": [1,2]]
var value = https://www.cnblogs.com/ZJT7098/p/(dic["a"] as! [Int])[0]
難點是,我們如何去決議包含自定義型別的陣列呢?
要知道 [Location] 、[User]和 [String] 可是不同型別.
原始型別畢竟數量有限,每個型別判斷一次沒問題,
但對于自定義的型別,以我目前的能力,不知道如何寫出兼容不同字典的決議代碼?很是頭大,
if let dic["a"] as [Location] {
//...
} else if dic["a"] as [User] {
....
}
// ...無窮無盡的自定義型別
新的思考
能否像弱型別語言那樣(如JavaScript),我可以這樣去訪問一個欄位 dic["a"][0] ?
而不用在乎 dic["a"]是不是陣列,也不關心它是個什么型別的陣列,假如它是個陣列,那就回傳相應索引的值;假如不是個陣列,就回傳nil,
這樣的話,有2個好處:
- 對于讀取,因為我們可以不必在乎是陣列型別,管你是[Location]還是[User],我知道你是個陣列就行,這樣可以寫出通用的遍歷代碼,
- 對于寫入,我們可以很容易的通過拼接的方式來修改嵌套欄位,
站在巨人的肩膀
在網上查閱資料,發現SwiftyJSON框架,
官方使用示例:
let json = JSON(data: dataFromNetworking)
if let userName = json[0]["user"]["name"].string {
//Now you got your value
}
看起來符合我的預期,
它的原理是把字典封裝到它自定義的JSON結構體里,
通過JSON.object屬性進行get、set操作,
這個object實際上通過型別判斷,回傳、修改不同的成員變數,
以下是SwiftyJSON的部分原始碼:
fileprivate var rawArray: [Any] = []
fileprivate var rawDictionary: [String: Any] = [:]
fileprivate var rawString: String = ""
fileprivate var rawNumber: NSNumber = 0
fileprivate var rawNull: NSNull = NSNull()
fileprivate var rawBool: Bool = false
/// Object in JSON
public var object: Any {
get {
switch type {
case .array: return rawArray
case .dictionary: return rawDictionary
case .string: return rawString
case .number: return rawNumber
case .bool: return rawBool
default: return rawNull
}
}
set {
//...
}
}
最終可行方案
初始化結構體,并轉為JSON,
使用KeyPath,作為欄位的唯一索引,格式如:"user.name"、"user.groups.0",
并且,我為KeyPath方案寫了個工具函式,1.可獲取JSON所有欄位的KeyPath,2. 可通過JSON[KeyPath]的方式修改欄位值,
這樣,就完全攻克讀、寫的技術難點了
- 遍歷JSON中的欄位值,判斷型別顯示相應UI;【其實就是遍歷KeyPath】
- 能通過UI控制元件修改原JSON相應欄位;[其實就是把JSON和KeyPath傳給UI]
原始碼
https://gitee.com/tamiapp/swift-ui-struct-to-view
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/286139.html
標籤:iOS
