In 7.3/9/2+ Swift how to disable rotation animation, when device rotates?

自闭症网瘾萝莉.ら 提交于 2019-12-03 10:16:26

You can use Method swizzling.

This means to are going to change calls to "viewWillTransitionToSize" on any view controller in your application to call "genericViewWillTransitionToSize" instead.
This way you do not have to use subclass, or repeated code over your application.

With that sad, you should be very carful with swizzling, with great power comes great responsibility. Put the class in a place that you, or the next programmer after you, will know how to find it, when he will want to return the rotation animations to view controllers.

extension UIViewController {

    public override static func initialize() {
        struct Static {
            static var token: dispatch_once_t = 0
        }

        dispatch_once(&Static.token) {
            let originalSelector = #selector(UIViewController.viewWillTransitionToSize(_:withTransitionCoordinator:))
            let swizzledSelector = #selector(UIViewController.genericViewWillTransitionToSize(_:withTransitionCoordinator:))

            let originalMethod = class_getInstanceMethod(self, originalSelector)
            let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)

            let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))

            if didAddMethod {
                class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
            } else {
                method_exchangeImplementations(originalMethod, swizzledMethod);
            }
        }
    }

    // MARK: - Method Swizzling
    func genericViewWillTransitionToSize(size:CGSize,
                                           withTransitionCoordinator coordinator:UIViewControllerTransitionCoordinator)
    {
        self.genericViewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
        coordinator.animateAlongsideTransition(nil, completion:
            {_ in
                UIView.setAnimationsEnabled(true)
        })
        UIView.setAnimationsEnabled(false)
    }
}
bzz

As far as I know, there is no better way to do it.

Although you can declare a separate class with this method and make all view controllers in your app its subclasses.

class NoRotateAnimationVC: UIViewController {
    override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
        UIView.setAnimationsEnabled(false)
        coordinator.notifyWhenInteractionEndsUsingBlock {_ in UIView.setAnimationsEnabled(true)}
    }
}

When you rotate the device, all view controllers whose views need to change their sizes receive viewWillTransitionToSize method invocation.

You need to declare this new class once in your app and then change all your view controller declarations from class MyViewController: UIViewController to MyViewController: NoRotateAnimationVC.

The provided implementation disables all animations and reenables them after the transition. So if you override this method in only one View Controller, as long as its view will change size as a result of a rotation, it will disable rotation animations everywhere. But if that view controller is not active, animations won't be disabled.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!