首發: http://www.lxweimin.com/p/42a84c9079c1
不知不覺就成了UITableView的重度患者,應對各種需求(比如換順序、按條件顯示內容、插廣告、各處插廣告)真是舒心。
但是近來隨著使用漸多,某些情況也顯得捉襟見肘起來:
問題一:首先是老大難 auto layout
使用auto layout的過程中,我始終覺得蘋果欠我們一個auto layout的初設函數:要求其在view frame初始化后,且view還未顯示時被調用;
先說說UIViewController
- 對UIViewController而言,比較推薦的auto layout的初設函數是
viewDidLoad
(見這個回復:Where should I be setting autolayout constraints when creating views programatically)。然而在viewDidLoad
中,view的frame并未得到初始化,部分依賴于實際尺寸的constraint又該如何設置呢? - 還有一種做法是選用
viewDidLayoutSubviews
作為auto layout的初設函數,這里滿足上面說的兩個條件,但是需要加上一個標志位,用來判定是不是第一次(view還未顯示時)調用。丑爆了!
回到UITableViewCell
對于Cell而言,auto layout的初設函數應該選用哪個?比如下例:
cell上有一個view,要求在3.5寸屏上的大小為36x36,在4寸屏上的為50x50,在4.7寸屏上為60x60,在5.5寸屏上位68x68(別問為什么,就是這么任性)。這個constraint如何設置?
很多人會說layoutSubviews
,然而:
- 同
viewDidLayoutSubviews
,要在layoutSubviews
中判斷是否為初次加載,需要額外參數一枚
- iOS9上,
layoutSubviews
有bug,見我的帖子,layoutSubviews
在cell加入view hierachy之前就被dequeueReusableCell......所調用了,簡直不可原諒。
問題二:其次是逐漸增多的動畫效果
動畫的需求和上面提到的auto layout的初設函數有些類似,同樣需要:
- 初始化后的frame
- 明確的timing:cell顯示在屏幕上以后
由于和問題一類似,就不展開了。
解決問題的思路
在思考如何解決上述問題的過程中,特別是cell的layoutSubviews在iOS9上的問題,使我不得不考慮尋求另外的函數入口。
自然而然,我想到了UIViewController的生命周期函數,暫時稱之為Lifecycle events吧。viewWillAppear, viewDidAppear, viewDidLayoutSubviews之類的回調函數,使我們可以從容的布置代碼。
為了實現這個目標,需要找到跟cell生命周期相關的各種函數,比如定義在UITableViewDelegate中的tableView:willDisplayCell:forIndexPath:
以及tableView:didEndDisplayCell:forIndexPath:
。在這兩個函數中觸發cellWillAppear
以及cellDidDisappear
,不能更贊!然而這兩個是optional delegate,并沒有具體的實現,如何加以利用呢?