在了解控制器的生命周期之後,我們都知道viewWillAppear:方法是在控制器的view將要顯示的時候調用的,而viewWillDisappear:方法是在控制器的view將要隱藏的時候調用。很多時候我們根據自身需要將相關代碼邏輯添加到這兩個方法中,我們看下如下代碼片段:
監聽鍵盤的通知代碼
這段代碼是在控制器的viewDidLoad:方法中注冊了一個鍵盤彈出的通知和鍵盤隱藏的通知,然後在調用到相關方法時分別在控制台打印,在viewWillDisappear:界面即將隱藏的時候移除通知,具體效果如下圖:
代碼運行效果圖
這看上去沒什麼問題,鍵盤的顯示和隱藏也都能監聽到。尼瑪!被騙了!?
其實並不然,細心的開發人員會知道,蘋果在iOS7中增加了導航控制器側滑返回功能,現在絕大多數App都使用了這項功能(有些App重寫了自帶的返回鍵之後忘記開啟左滑返回手勢了)。那麼這項功能會帶來什麼問題呢?我們接著看下面的操作:
側滑效果圖
隨著iPhone手機屏幕越來越大,左上角的返回按鈕早已夠不到(原諒我手小= =!),很多“手賤”的人喜歡通過這種側滑的形式返回上一個界面(其實說的是我。。。),而這種側滑返回會出現什麼問題呢?當觸發側滑返回時會調用系統自帶的viewWillDisappear:方法,在該方法中將監聽鍵盤顯示和隱藏的通知移除後,要是這時候用戶取消了側滑返回(即回到了原始狀態),那麼再點擊界面上的textField喚出鍵盤,是不會發送鍵盤顯示和隱藏的通知了,因為通知已被移除。。。
那麼遇到這種情況有什麼方法解決麼?
我這裡提供兩種解決方案:
1、將注冊監聽鍵盤顯示和隱藏的代碼放到viewWillAppear:方法中
因為在觸發側滑返回後又取消側滑,則會調用viewWillAppear:方法。那麼如果側滑返回將通知移除,則在取消側滑時又會將通知重新添加進去。
2、將移除通知的代碼放到dealloc方法中
dealloc方法是在控制器銷毀之時調用的。這個時候移除通知而不是在viewWillDisappear:方法中移除可以有效避免上述的問題。既然控制器都銷毀了,那麼還留著相關的通知干嘛?該移除的移除。
上面給出了兩種解決方案,要說哪種最優,那肯定非第二種莫屬了。
我在這裡可以舉個例子。假如我們現在有這麼個場景:在控制器的view上有個label,在label上添加一個手勢(一般手勢都是在創建完label之後添加的),假設我在viewWillDisappear:方法中移除該手勢,則此時用戶側滑返回之時又取消側滑返回,那麼原先在label上的手勢卻再也添加不回來了(這裡label一般在viewDidLoad方法中創建),因為viewDidLoad方法不會再次調用。而第二種方法卻可以有效避免這種情況,這樣就可以避免我這種“手賤”的任意搗鼓了,是不是很完美呢?
最後,我們再來總結下重點:
1、iOS7新增加了導航控制器側滑手勢,當觸發側滑返回時,會調用系統的viewWillDisappear:方法,取消側滑返回時又會調用viewWillAppear:方法。
2、在做手勢和通知等一系列操作之時盡量在dealloc方法中執行,添加通知盡量在viewDidLoad等一次性方法中執行。
3、在viewWillAppear:、viewWillDisappear:、viewDidAppear:、viewDidDisappear:等類似於這種會多次調用的系統方法中添加代碼時,一定要多考慮業務邏輯,以免出現不必要的麻煩。