12.一键搞定iOS16横竖屏切换

前言

近期同事反馈视频横屏的功能失效了,在才发现 iOS16 下以前的方式无法使用了。于是完善了一些自己之前写的横竖屏切换的拓展。

一、 iOS16 之前

1.1 切换横屏

UIDevice.current.setValue(UIDeviceOrientation.landscapeLeft.rawValue, forKey: "orientation")

1.2 切换竖屏

UIDevice.current.setValue(UIDeviceOrientation.portrait.rawValue, forKey: "orientation")

1.3 切换结果监听

通过系统通知 UIDevice.orientationDidChangeNotification 监听提切换动作。

@objc
private func orientationDidChange(noti: Notification) {
    guard
        let device = noti.object as? UIDevice
    else {
        return
    }
    if device.orientation.isLandscape {
        print("横屏")
    } else {
        print("竖屏")
    }
}

二、 iOS16

更新了 iOS16 之后,发现上面的都没效果了,就...很可爱。iOS16 之后需要通过 Scene 来进行横竖屏的切换控制。

核心代码如下:

func enterFullScreen() {
    guard #available(iOS 16.0, *) else {
        UIDevice.current.setValue(UIDeviceOrientation.landscapeLeft.rawValue, forKey: "orientation")
        return
    }
    switchMode(full: true)
}

func exitFullScreen() {
    guard #available(iOS 16.0, *) else {
        UIDevice.current.setValue(UIDeviceOrientation.portrait.rawValue, forKey: "orientation")
        return
    }
    switchMode(full: false)
}

@available(iOS 16.0, *)
private func switchMode(full: Bool) {
    guard
        let scence = UIApplication.shared.connectedScenes.first as? UIWindowScene
    else {
        return
    }
    let orientation: UIInterfaceOrientationMask = full ? .landscape : .portrait
    let geometryPreferencesIOS = UIWindowScene.GeometryPreferences.iOS(interfaceOrientations: orientation)
    scence.requestGeometryUpdate(geometryPreferencesIOS) { error in
    }
}

三、RyukieSwifty/FullScreen

我对这些逻辑进行了封装可以简单的接入到项目之中。也提供了示例程序。GitHub: RyukieSwifty/FullScreen

pods 接入:

pod 'RyukieSwifty/FullScreen'

下面以一个 UIViewController 为例:

import UIKit
import RyukieSwifty

class FullScreenViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
    }
    
    // MARK: - Life
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        swifty.exitFullScreen()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        swifty.needFullScreen()
    }
    
    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        if size.width > size.height {
            switchButton.isSelected = true
        } else {
            switchButton.isSelected = false
        }
    }
    // MARK: - Function-Public
    
    // MARK: - Function-Private
    
    // MARK: UI
    private func setupUI() {
        view.backgroundColor = .white
        
        switchButton
            .added(to: view)
            .layout { make in
                make?.center.equalToSuperview()
            }
    }
    
    // MARK: Buiness
    
    // MARK: Action
    @objc
    private func switchAction() {
        switchButton.isSelected ? swifty.exitFullScreen() : swifty.enterFullScreen()
    }
    
    // MARK: Request
    
    // MARK: - VarLet-Public
    
    // MARK: - VarLet-Private
    private lazy var switchButton: UIButton = {
        return UIButton()
            .config {
                $0.setTitleColor(.black, for: .normal)
                $0.setTitle("切换为横屏", for: .normal)
                $0.setTitle("切换为竖屏", for: .selected)
                $0.addTarget(self, action: #selector(switchAction), for: .touchUpInside)
            }
    }()
}

extension AppDelegate {
    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return application.swifty.supportedInterfaceOrientations
    }
}

Last updated