swift 3 关于屏幕旋转的测试
开发中有这么个需求:主页面是竖屏显示,进入一个类似于播放视频的子页面需要横屏显示,退出到主页面,恢复竖屏
参考:小胖说swift11——– ios 进入某个VC强转为横屏,出VC后复原
下面记录实现过程:
首先创建项目,配置没做任何修改,基本结构如下:
在Appdelegate中添加代码:
var orientationPortrait = true //记录是否为竖屏
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if self.orientationPortrait {
return .portrait
} else{
return .landscapeRight
}
}
在FirstViewController中添加代码:
override func viewWillAppear(_ animated: Bool) { //设置主页面竖屏
super.viewWillAppear(animated)
let value = UIInterfaceOrientation.portrait.rawValue
(UIApplication.shared.delegate as! AppDelegate).orientationPortrait = true
UIDevice.current.setValue(value, forKey: "orientation")
}
在SecondViewController中添加代码:
override func viewWillAppear(_ animated: Bool) { //设置子页面横屏
super.viewWillAppear(animated)
let value = UIInterfaceOrientation.landscapeRight.rawValue
(UIApplication.shared.delegate as! AppDelegate).orientationPortrait = false
UIDevice.current.setValue(value, forKey: "orientation")
}
override func viewWillDisappear(_ animated: Bool) { //返回主页面设置竖屏
super.viewWillDisappear(animated)
let value = UIInterfaceOrientation.portrait.rawValue
(UIApplication.shared.delegate as! AppDelegate).orientationPortrait = true
UIDevice.current.setValue(value, forKey: "orientation")
}
实现上述代码,基本实现了需求,但通过测试,发现一个问题:
重现方式如下:1:将手机的旋转锁定打开 -> 2:在竖屏情况打开APP -> 3:将手机横过来 -> 4:点击push进入second页面,发现second页面是竖屏的。
解决方法:
通过在Appdelegate的supportedInterfaceOrientationsFor方法中打断点分析: func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask 的触发方式有两种
一种是旋转手机时不定时触发(有时旋转会调用,有时不会):
一种是在调用UIDevice.current.setValue(value, forKey: “orientation”)时触发
修改SecondViewController的方法,打日志查看:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let value = UIInterfaceOrientation.landscapeRight.rawValue
(UIApplication.shared.delegate as! AppDelegate).orientationPortrait = false
let sysyemValue = UIDevice.current.value(forKey: "orientation")
print("system value = \(sysyemValue)")
print("setValue = \(value)")
UIDevice.current.setValue(value, forKey: "orientation")
}
当正常操作是输出为:
system value = Optional(1)
setValue = 3
当重复上述的错误操作时,输出为:
system value = Optional(3)
setValue = 3
发现当当前sysyemValue与要设置的value相同时,不会触发 func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask
猜测 supportedInterfaceOrientationsFor 的触发方式类似于KVO(类似而已),即当orientation的值确实有变化时才会触发supportedInterfaceOrientationsFor
尝试手动调用KVO:
在viewWillAppear方法中添加:
UIDevice.current.willChangeValue(forKey: "orientation")
UIDevice.current.didChangeValue(forKey: "orientation")
然而并没有什么卵用,需要研究下swift的kvo,待续
在setValue前先设置一个其他值
UIDevice.current.setValue(UIInterfaceOrientation.unknown.rawValue, forKey: "orientation")
UIDevice.current.setValue(value, forKey: "orientation")
如此解决了上面的bug