授權轉載,作者:Cyandev
最近做東西的時候發現了這樣的一個問題,相信大家也都遇到過,當你使用 UISearchController 在 UITableView 中實現搜索條,在搜索框已經激活並推入新的 VC 的時候會發生搜索框重疊的情況。(如圖)
起初我以為這是 iOS 的一個 Bug,就用手動 dismiss 的方式解決了。忙完回頭再看蘋果的文檔,我恍然大悟,其實只需要設置一個屬性就能完美解決這個問題!
那就是 definesPresentationContext 這個布爾值。
平時看起來沒什麼卵用的一個屬性在這裡究竟起到了什麼作用呢?要解釋這個問題,我們就要復習一下 “presentViewController” 的有關知識。
首先我們需要知道的是,UISearchController 搜索框展開的過程其實就是 SearchBar 觸發了一個 “presentViewController” 的動作,所以一切問題就出在了 present 的方式上。系統為我們提供了許多呈現樣式,我們只需要設置要呈現的 VC 的 modalPresentationStyle 屬性就能實現多種效果,通常我們使用到的是:
FullScreen: 顧名思義,它會在全屏范圍內呈現一個視圖控制器,效果其實在 iPad 或 iPhone 6/6s Plus 上體現的明顯。
CurrentContext: 在當前上下文中顯示一個視圖控制器,如果你使用 iPad 或 iPhone 6/6s Plus,你可能見過 Master / Detail 的視圖,其中左右兩個視圖分別都可以作為一個 Context,使用該模式,新的視圖控制器就只會顯示在制定的上下文中了。
OverCurrentContext: 與上面的區別是,這種方式會讓父視圖和正在呈現的視圖控制器同時顯示,通常我們要顯示一個 HUD 的時候就需要這個模式,不然背景就會變成黑色。
Popover: 彈出氣泡樣式。
Custom: 自定義,通過 delegate 獲取到 UIPresentationController 進而控制視圖控制器的呈現效果。
這裡,UISearchController 僅支持 OverCurrentContext、Popover 因此默認情況下使用的就是 OverCurrentContext 方式。根據文檔:
當一個視圖控制器以 OverCurrentContext 的方式被呈現時,它會向上尋找一個 definesPresentationContext 屬性為真的父視圖控制器,並在它之上顯示這個視圖控制器。
到這裡,我們就知道為什麼文章開頭的問題會出現了。因為我們沒有指定任何視圖控制器為 Presentation Context,那麼 UISearchController 就會顯示在最根部的 UINavigationController 之上,當然就會遮擋導航條了。但是當我們給 UINavigationController 中某一級的 VC 設置了 definesPresentationContext,UISearchController 就會顯示在那個 VC 之上,而不會遮擋整個 UINavigationController。
我們看看這種情況下的視圖層次:
再看看沒有定義 Presentation Context 的視圖層次:
是不是一目了然了呢。