Observe interface orientation from the View

481 Views Asked by At

I was using NotificationCenter to observe interfaceOrientation change by UIApplication.willChangeStatusBarOrientationNotification. But UIApplication.willChangeStatusBarOrientationNotification is now marked deprecated. It is suggested to use viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator, but this is the method called from the ViewController. I have a subclass of UIView that needs this internally, and Im exposing this View as a framework. I would like to be able to still maintain this functionality without the need to be explicitly called from the ViewController. Is there another option to achieve this directly inside View? I tried observing UIWindowScene.interfaceOrientation with KVO, but this didn't work.

public extension Notification.Name {
    static let willChangeStatusBarOrientationNotification = UIApplication.willChangeStatusBarOrientationNotification    
}

...

@objc private func statusBarOrientationWillChange(notification: Notification) {
    if let orientationRawValue = notification.userInfo?[UIApplication.statusBarOrientationUserInfoKey] as? Int, let orientation = AVCaptureVideoOrientation(rawValue: orientationRawValue) {
        configureVideoOrientation(interfaceOrientation: orientation)
        updateSceneInformation()
    }
}

...

private func initialize() {
    NotificationCenter.default.addObserver(self, selector: #selector(statusBarOrientationWillChange(notification:)), name: .willChangeStatusBarOrientationNotification, object: nil)

}

enter image description here

1

There are 1 best solutions below

0
rolling_codes On

Try this. It seems to only be available as a post-orientation-change notification and not a pre-orientation-change notification, but it should not produce a deprecation warning. Note that the device orientation is of the UIDeviceOrientation type, not the UIInterfaceOrientation type.

public class MyView: UIView {

    public override init(frame: CGRect) {
        super.init(frame: frame)
        NotificationCenter.default.
                addObserver(self, 
                            selector: #selector(deviceOrientationDidChange), 
                            name: UIDevice.orientationDidChangeNotification, 
                            object: nil)
    }

    public required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    @objc
    private func deviceOrientationDidChange(_ notification: Notification) {
        guard UIDevice.current.orientation.isValidInterfaceOrientation,
              let orientation = AVCaptureVideoOrientation(rawValue: UIDevice.current.orientation.rawValue) 
            else { return }
        configureVideoOrientation(interfaceOrientation: orientation)
        updateSceneInformation()
    }

}