1

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

Damian Dudycz
  • 2,622
  • 19
  • 38
  • It's marked deprecated in the Apple developer docs, but you can still use it. I don't see them obsoleting this functionality any time soon, if ever, because of how crucial it is to many applications, and the lack of a suitable alternative like you mention – rolling_codes Dec 19 '19 at 16:32
  • Yeah I know, but it's bugging me to see this single warning in the entire project. Maybe there is some other solution, so I could adapt. – Damian Dudycz Dec 19 '19 at 16:33
  • In that case, can you share more code so that if we were to copy your class into Xcode we would see the same warning? – rolling_codes Dec 19 '19 at 16:34
  • I have added some small code samples, I can't share the whole project. But actually there is no more to it, its just a function in UIView subclass that uses UIApplication.willChangeStatusBarOrientationNotification and UIApplication.statusBarOrientationUserInfoKey – Damian Dudycz Dec 19 '19 at 16:38
  • where are your last two methods located? Inside of a class that extends `UIView`? – rolling_codes Dec 19 '19 at 16:41
  • Yes, inside this UIView subclass – Damian Dudycz Dec 19 '19 at 16:42
  • I am not seeing a warning in a brand new `12.1` build target project. Can you share the warning text? – rolling_codes Dec 19 '19 at 16:44
  • It's for iOS 13. I've added the picture – Damian Dudycz Dec 19 '19 at 16:45
  • You can try posting a custom notification when the root view controller changes orientation. It's a shame Apple does not have a suitable alternative for this functionality. Good question. You should recommend it as an addition in the swift evolution git project – rolling_codes Dec 19 '19 at 17:03
  • Yeah I could use custom notification, but this still enforces some extra work on the user of this class. Guess there might not be a perfect solution. I will probably stay with current implementation, until I can find something better. Thanks for comments. – Damian Dudycz Dec 19 '19 at 17:07
  • Added an answer that might address your problem – rolling_codes Dec 19 '19 at 18:07

1 Answers1

0

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()
    }

}
rolling_codes
  • 15,174
  • 22
  • 76
  • 112