表驱动法在iOS中的应用

表驱动法(Table-Driven Methods)出自《代码大全》。它是一种编程模式——从表里面查找信息而不使用逻辑语句。

表提供了一种负责的逻辑和继承结构的替换方案。如果你发现自己对某个应用程序的逻辑或继承树关系感到困惑,那么问问自己它是否可以通过一个查询表来加以简化。

在实际使用中,我们常常在cellForRow中写上了很多的逻辑判断语句。在大多数情况下,可以通过表驱动法更便捷地达到目的。

最简单的例子:
初学 iOS 时,想必大家都写过下面类似的代码:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier")! 
        if indexPath.row == 0 {
            cell.textLabel?.text = "title0"
        } else if indexPath.row == 1 {
            cell.textLabel?.text = "title1"
        } else if indexPath.row == 2 {
            cell.textLabel?.text = "title2"
        }

    return cell
}

根据表驱动法的思路,可以用以下方式替代:

var contents: [String] = []
    override func viewDidLoad() {
        super.viewDidLoad()
        contents = ["title0", "title1", "title2"]
    }

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier")!
        let title = contents[indexPath.row]
        cell.textLabel?.text = title

    return cell
}

当然,实际情况不可能这么简单。比如要创建一个简单的设置界面,这个时候contents可以包含字典以设置cell属性。
例如:

var contents:[[String: Any]] = []
override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cellid")
        
    for x in 0 ..< 3 {
       let dict = [
            "id" : "cellid",
            "title" : "title" + String(x),
            "detail" : "detail" + String(x),
            "height" : 44.0
        ] as [String : Any]
        contents.append(dict)
    }
    
}


override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return contents.count
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    let dict = contents[indexPath.row] as [String : Any]
    let height = dict["height"] as? Double
    return CGFloat(height!)
    
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cellid")!
    
    let dict = contents[indexPath.row] as [String : Any]
    let title = dict["title"] as? String

    cell.textLabel?.text = title
    
    return cell
}

这个时候就不需要同时在 cellForRow heightForRow 进行判断去设置属性了。

进一步,可以将上例中的字典替存储在本地文件(json或者plist,二者没有明显的性能差距)。简单的json文件示例:

{
     "applyInfo" : [
        {
            "header" : "",
            "height" : 0.0001,
            "footer" : "",
            "footerHeight" : 20,
            "content" : [
                {
                    "title" : "借款编号",
                    "height" : 50,
                    "detail" : "",
                    "id" : "someID"
                },
                {
                    "title" : "产品类型",
                    "height" : 50,
                    "detail" : "",
                    "id" : "someID"
                }
            ]
        },
        {
            "header" : "",
            "height" : 50,
            "footer" : "",
            "footerHeight" : 0.0001,
            "content" : [
                {
                    "title" : "姓名",
                    "height" : 50,
                    "detail" : "",
                    "id" : "someID"
                },
                {
                    "title" : "性别",
                    "height" : 50,
                    "detail" : "",
                    "id" : "someID"
                },
            ]
        },
    ]
}

每次取出时,转换成cellModel对象。如果有多个Section,再增加一层sectionModel
通过这种方式,封装成一个基类FormController。结合ReactiveCocoadidSelectRow的代码写在cellForRow里,可以方便的写出复杂的填表页面。

具体代码,大家可以参考 Form

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,347评论 19 139
  • 何家,在帝都是个比较特殊的存在,它算不上大家族,但也不是小门小户。何家家规,长子或长女继承家族成为新一代家主,家...
    kk不言阅读 1,547评论 0 0
  • 如果离开 请静悄悄地走 这是一个深秋 适合远走 如果离开 请静悄悄地走 不要让我看到你秋水般的眼眸 我怕我会不忍挽...
    思政2014马金兰阅读 1,540评论 0 1
  • 一 突然发现,我们曾放言要找个又高大又帅气又博学还对自己好的男生,并以此为箴言。但最后选择的,往往是那个长相不出众...
    陈米粒啊阅读 3,952评论 5 5
  • 姓名:陆振村~公司:浙江均泰建设有限公司 【日精进打卡第23天】 【知~学习】 《六项精进》大纲1遍 共25遍 《...
    陆振村阅读 1,592评论 0 0