iOS開發(fā)中挟纱,經(jīng)常會(huì)碰到某些頁面需要支持橫屏顯示撕氧,某些又僅支持豎屏顯示摧找,那怎么樣才能比較完美的實(shí)現(xiàn)各個(gè)界面的橫豎屏設(shè)置,有不相互影響呢牢硅?
經(jīng)過幾個(gè)項(xiàng)目的實(shí)踐比較蹬耘,個(gè)人感覺讓各個(gè)viewController自己來控制自己的橫豎屏顯示是最好的!<跤唷综苔!
問題是怎么設(shè)置才最簡單方便不容易出錯(cuò)~
注:以下全部是iOS6以后的方法,iOS6之前的太久遠(yuǎn)了位岔,就不提了如筛;
這里僅涉及設(shè)置的方法,具體轉(zhuǎn)屏的方法抒抬,有空再寫杨刨;
首先,要確定APP支持哪些方向
可以通過兩種方式來確定:
-
在工程設(shè)置處勾選
工程設(shè)置
或者在或者在info.plist中設(shè)置
info.plist中設(shè)置
這兩個(gè)地方是等價(jià)的擦剑,改了其中一個(gè)地方妖胀,另一個(gè)也會(huì)跟著變; - 在AppDelegate中實(shí)現(xiàn)方法
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return .allButUpsideDown
}
1或者2必須實(shí)現(xiàn)至少一個(gè)才行惠勒;
什么赚抡?你說兩個(gè)都沒實(shí)現(xiàn)?那系統(tǒng)會(huì)按默認(rèn)的.allButUpsideDown來處理纠屋。涂臣。。
什么什么巾遭?你說兩個(gè)都實(shí)現(xiàn)了設(shè)置的值還不一樣肉康?那系統(tǒng)會(huì)以AppDelegate中實(shí)現(xiàn)的代碼為準(zhǔn)。灼舍。吼和。
其次,要確定viewController支持的方向
viewController通過以下方法來確定:
open override var shouldAutorotate: Bool {
return false
}
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
open override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return .portrait
}
第一個(gè)方法確定viewController是否會(huì)自動(dòng)旋轉(zhuǎn)骑素,第二個(gè)方法確定viewController支持哪些方向炫乓,第三方方法確定viewController彈出來時(shí)的方向;
需要注意的是:
這幾個(gè)方法只有當(dāng)viewController是window的rootViewController或者viewController是present出來時(shí)献丑,才會(huì)起作用末捣!
這幾個(gè)方法只有當(dāng)viewController是window的rootViewController或者viewController是present出來時(shí),才會(huì)起作用创橄!
這幾個(gè)方法只有當(dāng)viewController是window的rootViewController或者viewController是present出來時(shí)箩做,才會(huì)起作用!
重要的事情說三遍
也就是說妥畏,如果app是常見的tabBarController+navigationController+viewController的結(jié)構(gòu)的話邦邦,rootViewController是tabBarController安吁,
所以只有tabBarController的這三個(gè)方法會(huì)被調(diào)用!
那怎么實(shí)現(xiàn)開頭說的讓各個(gè)viewController來控制自己的方向呢燃辖?
其實(shí)很簡單鬼店,因?yàn)閠abBarController和navigationController都是viewController的容器,讓他們返回當(dāng)前顯示的viewController的相應(yīng)方法就行了黔龟!
以navigationController為例妇智,就是:
open override var shouldAutorotate: Bool {
if let viewController = self.topViewController {
return viewController.shouldAutorotate
} else {
return false
}
}
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if let viewController = self.topViewController {
return viewController.supportedInterfaceOrientations
} else {
return .portrait
}
}
open override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
if let viewController = self.topViewController {
return viewController.preferredInterfaceOrientationForPresentation
} else {
return .portrait
}
}
注意:viewController最終支持的方向是以上app支持方向和viewController支持方向兩個(gè)規(guī)則的交集,如果交集為空氏身,就會(huì)crashN±狻!观谦!
基本原理知道了拉盾,也該回答最初的問題了,簡單方便又不容易出錯(cuò)的設(shè)置方法就是
結(jié)論:寫基類
這里需要至少三個(gè)基類豁状,分別繼承tabBarController捉偏,navigationController和viewController;
在其中分別實(shí)現(xiàn)轉(zhuǎn)屏方法泻红,然后項(xiàng)目中所有的其他類夭禽,都繼承這幾個(gè)基類;
然后谊路,在需要支持不同方向的viewController中讹躯,重載轉(zhuǎn)屏的三個(gè)方法,就大功告成了~
例:
這里OJSTabBarController缠劝,OJSNavigationController潮梯,OJSViewController分別集成自對應(yīng)的UIViewController
extension OJSTabBarController {
//這里,如果selectedViewController是navigationController惨恭,因?yàn)閚avigationController也是返回它的topViewController的狀態(tài)秉馏,所以最終還是各個(gè)viewController自己來控制自己的狀態(tài)
open override var shouldAutorotate: Bool {
if let tempViewController = self.selectedViewController {
return tempViewController.shouldAutorotate
} else {
return false
}
}
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if let tempViewController = self.selectedViewController {
return tempViewController.supportedInterfaceOrientations
} else {
return UIInterfaceOrientationMask.portrait
}
}
open override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
if let tempViewController = self.selectedViewController {
return tempViewController.preferredInterfaceOrientationForPresentation
} else {
return UIInterfaceOrientation.portrait
}
}
}
extension OJSNavigationController {
//這里只需要返回self.topViewController的相應(yīng)屬性,讓各個(gè)viewController自己控制就行了
//present出來的viewController本來就是受自己控制脱羡,跟nav無關(guān)
open override var shouldAutorotate: Bool {
if let viewController = self.topViewController {
return viewController.shouldAutorotate
} else {
return false
}
}
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if let viewController = self.topViewController {
return viewController.supportedInterfaceOrientations
} else {
return .portrait
}
}
open override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
if let viewController = self.topViewController {
return viewController.preferredInterfaceOrientationForPresentation
} else {
return .portrait
}
}
}
extension OJSViewController {
open override var shouldAutorotate: Bool {
return false
}
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
open override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return .portrait
}
}
這樣做的好處是:
每個(gè)viewController都有默認(rèn)的轉(zhuǎn)屏設(shè)置萝究,不會(huì)因?yàn)槁懥舜a而出現(xiàn)不應(yīng)該出現(xiàn)的旋轉(zhuǎn);
每個(gè)viewController是自己控制自己的方向锉罐,不會(huì)對前后viewController有任何影響
需要特殊方向的viewController帆竹,僅實(shí)現(xiàn)自己的方法就行,不用再在rootViewController中做一大堆判斷脓规;
栽连。。侨舆。秒紧。舷暮。。
彩蛋
之前提交appstore時(shí)遇到個(gè)極其奇葩的問題噩茄,蘋果審核人員用iPad裝我們的iPhone app,然后發(fā)現(xiàn)他的iPad橫著啟動(dòng)app時(shí)界面全亂了复颈,
然后他就截了個(gè)圖绩聘,把我們的app拒掉了。耗啦。凿菩。。帜讲。衅谷。
當(dāng)時(shí)我的內(nèi)心真是極其崩潰的,似将,获黔,iPad豎著啟動(dòng)app時(shí),就一切正常在验,橫著啟動(dòng)app時(shí)玷氏,界面就亂套了。腋舌。盏触。
這想想應(yīng)該是蘋果的鍋啊?榻取T薇纭!
后來偶然發(fā)現(xiàn)個(gè)非常規(guī)的解決方法:
在工程設(shè)置處設(shè)置app只支持portrait授艰,然后在AppDelegate中設(shè)置為支持其他辨嗽;這樣app啟動(dòng)的時(shí)候就會(huì)強(qiáng)制用豎屏方式啟動(dòng),
iPad上的問題就解決了想诅。召庞。。蘋果也給審核通過了来破。篮灼。。