优雅地定制 UITableViewController

在此宣传一下自己的博客,之后文章的首发会在博客上。

UITableViewController 是专门设计用来应付UITableView的视图控制器,讲道理用它是比用普通的ViewController + Data Source & Delegate 要方便很多的,它有很多便利的功能能加速我们开发TableViewController。

  • clearSelectionOnViewWillAppear
    若是在UIViewController上自己实现倒也是很简单。其实这个功能的名字几乎已经完全说明了他是怎么实现的。

  • 键盘监听与输入框防遮挡
    这个功能可以说是UITableViewController一大非常便利的功能。它提供了在列表视图中非常完美的输入框键盘防遮挡功能。只要你聚焦于其内部的某个输入框,他一定会以一种十分恰当的方式让聚焦框露出来。
    但我们自己在UIViewController上实现的类似功能是有些费劲的。

  • Refresh Control
    其内部的一个好处就是,在目前主流兼容的版本中,你不需要再做版本适配,因为它是从iOS 6起兼容的。而UIScrollView中的相同api是从iOS 10 起。如果你的项目是iOS 10以上起步的话,就忽略这个优点吧。

问题

UITableViewController的主控视图(UIViewController.view)是UITableView,而且他是继承了UIScrollView,所以当你直接往上面添加一个子视图(比如Toast、浮动按钮)的时候,你会发现这些子视图会跟着你页面一起上下滚动。
emmmm… 我当时在给公司项目接入toast的时候就是遇到了这个问题,所以我一怒之下抛弃了UITableViewController

UIViewController + Data Source & Delegate

如果我们直接用UIViewController,并使tableView作为其view的子视图的话,toast的问题就可以解决,因为toast所坐落的父视图并不是一个滚动视图。
就酱,我以为从此我找到了究极解决方案,直到有一天在我写Terrace这个库的时候,一个UITableViewCell内置输入框键盘防遮挡的效果迟迟不能实现成我满意的样子。就在这个时候,我想起了曾经被我抛弃的UITableViewController处理起键盘防遮挡如丝顺滑。我决定再试一次UITableViewController

Customizing

关键问题是要给tableView加个座垫儿。

作为子控制器

从iOS 5开始,苹果为UIViewController增加了子视图控制器概念,但类似的概念并不算苹果第一次提出,UINavigationController不就是导航栏爸爸管着一群视图控制器崽子们吗?

UITableViewController 做为子控制器:

class WrappedTableViewController : UITableViewController {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // 被父控制器添加为子视图后配置约束
        if let superview = self.parent?.view {
            self.tableView.translatesAutoresizingMaskIntoConstraints = false
            self.tableView.topAnchor.constraint(equalTo: superview.topAnchor).isActive = true
            self.tableView.bottomAnchor.constraint(equalTo: superview.bottomAnchor).isActive = true
            self.tableView.leftAnchor.constraint(equalTo: superview.leftAnchor).isActive = true
            self.tableView.rightAnchor.constraint(equalTo: superview.rightAnchor).isActive = true
        }
    }
}

UIViewController 父控制器:

class ViewController: UIViewController {
    private lazy var tableViewController = WrappedTableViewController(style: .plain)
    override func viewDidLoad() {
        super.viewDidLoad()
        self.addChild(self.tableViewController)
        self.view.addSubview(self.tableViewController.tableView)
    }
}

这种方式可能会显得仅仅起包裹作用的父控制器没什么事做,当一个座垫儿是不是有点大材小用了。

改变控制的tableView

var tableView: UITableView! { get set }

Returns the table view managed by the controller object.

既然它的目的是返回由控制器控制的table view object,我们可以通过override来达到我们的目的,告诉它谁才是真正的主角!

这次作为Container的就可以是一个UIView,而不是用UIViewController。

class ContainerView : UIView {
    var tableView = UITableView()
    // ... view configurations
}

敲黑板敲黑板!注意啦注意啦!

class TableViewController : UITableViewController {
    let containerView = ContainerView()
    
    // 控制我们自己的TableView
    override var tableView: UITableView! {
        get { return self.containerView.tableView }
        set {
            self.containerView.tableView = newValue
            newValue.delegate = self
            newValue.dataSource = self
        }
    }
    
    override func loadView() {
        self.view = self.containerView // 将主视图替换为自定义基底视图
        self.tableView.delegate = self
        self.tableView.dataSource = self
    }
}

首先在loadView配置本控制器显示的主视图不再是默认的tableView,而是我们准备的containerView。然后让tableViewgettersetter都指向我们自己的tableView别忘了指定dataSourcedelegate

写在最后

当时我在tableView上解决toast问题和输入框键盘遮挡问题,第一次使用UITableViewController的时候也是我第一次用UITableView的时候。当时还并没有深入了解视图控制器对视图的加载时机和自定义方式,直到后来学会了利用loadView方法。但那个时候我已经在UIViewController + DataSource & Delegate 的方式中走了很久,再直到后来一次在这个方式基础之上处理输入框键盘遮挡问题时觉得很麻烦,才在一次将注意力移回到UITableViewController上。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,092评论 1 32
  • 概述在iOS开发中UITableView可以说是使用最广泛的控件,我们平时使用的软件中到处都可以看到它的影子,类似...
    liudhkk阅读 9,007评论 3 38
  • 冥冥中,我会用起那么一种工具,来寄托我情感多年的喧嚣,我知道它不是默默,也不是微信,更不可能是我一直在用的空间,我...
    直面微笑阅读 121评论 2 2
  • 目前大家在筛选考研调剂信息的时候,会遇到这样一个尴尬的事情:跨校调剂,即使是同专业,复试的笔试科目也有差别,时间精...
    番薯姐姐丶阅读 1,139评论 0 0