2021年5月17日星期一

SwiftUI 结构体自动生成可编辑界面

2个关键点:一个是读取、一个是写入。
显示界面:读取结构体的字段名,字段类型,即可判断、显示相应的UI控件;
用户写入数据:需要知道每个UI控件和哪个字段进行绑定,另外,对字段需要有写的权限。

尝试Mirror【失败】

第一个尝试的方案是运用反射技术,在Swift中,使用的是Mirror。Mirror可以读取结构体的属性,但不能修改结构体。

尝试Dictionary【失败】

第二个尝试的方案是使用字典Dictionary。即可读取,也能写入。
具体步骤是:

  1. 初始化结构体
  2. 通过JSONSerialization序列化成字典
  3. 遍历字典显示界面。。。[卡住]

单单是在读取这里,就遇到一个棘手的问题。Swift是强类型的语言,所以读取Dictionary的嵌套字段,需要一长串的类型转换。这就很难写出简洁易懂的代码。
比如:

 var dic:[String: Any] = ["a": [1,2]] var value = (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个好处:

  1. 对于读取,因为我们可以不必在乎是数组类型,管你是[Location]还是[User],我知道你是个数组就行。这样可以写出通用的遍历代码。
  2. 对于写入,我们可以很容易的通过拼接的方式来修改嵌套字段。

站在巨人的肩膀

在网上查阅资料,发现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]的方式修改字段值。

这样,就完全攻克读、写的技术难点了

  1. 遍历JSON中的字段值,判断类型显示相应UI;【其实就是遍历KeyPath】
  2. 能通过UI控件修改原JSON相应字段;[其实就是把JSON和KeyPath传给UI]

源码

//整理后发出









原文转载:http://www.shaoqun.com/a/748782.html

跨境电商:https://www.ikjzd.com/

002315焦点科技:https://www.ikjzd.com/w/1831

邮乐网购物商城:https://www.ikjzd.com/w/1776


2个关键点:一个是读取、一个是写入。显示界面:读取结构体的字段名,字段类型,即可判断、显示相应的UI控件;用户写入数据:需要知道每个UI控件和哪个字段进行绑定,另外,对字段需要有写的权限。尝试Mirror【失败】第一个尝试的方案是运用反射技术,在Swift中,使用的是Mirror。Mirror可以读取结构体的属性,但不能修改结构体。尝试Dictionary【失败】第二个尝试的方案是使用字典Dict
prime day:https://www.ikjzd.com/w/131
c2c:https://www.ikjzd.com/w/1576
tineye:https://www.ikjzd.com/w/448
eBay宣布成立国际跨境贸易事业部,林奕彰出任执行总裁:https://www.ikjzd.com/home/1620
口述:不想为无能丈夫生下孩子:http://www.30bags.com/m/a/253308.html
刚搬来的漂亮女邻居 口述已婚男和离异女的暧昧经历:http://www.30bags.com/a/250452.html

没有评论:

发表评论