本文介绍了使用方法刷新在iOS13上的所有UIViewController实例上一次更改modalPresentationStyle的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

[Q& A] 是否可以在iOS 13上全局更改UIViewController.modalPresentationStyle值,使其表现得像在iOS 12(或更早版本)上一样?

[Q&A] Is it possible to change UIViewController.modalPresentationStyle value globally on iOS 13 so it behaves like it used to on iOS 12 (or earlier)?

为什么?

在iOS 13 SDK中,UIViewController.modalPresentationStyle属性的默认值已从UIModalPresentationFullScreen更改为UIModalPresentationAutomatic,据我所知,在iOS设备或至少在iPhone上已解析为UIModalPresentationPageSheet.

In iOS 13 SDK the default value of UIViewController.modalPresentationStyle property has been changed from UIModalPresentationFullScreen to UIModalPresentationAutomatic which is, as far as I know, resolved to UIModalPresentationPageSheet on iOS devices or at least on iPhones.

由于我已经工作了几年的项目变得非常庞大,所以在很多地方都提供了视图控制器.新的演示样式并不总是与我们的应用程序设计匹配,有时会导致UI崩溃.这就是为什么我们决定将UIViewController.modalPresentationStyle改回UIModalPresentationFullScreen,因为它是iOS13 SDK之前的版本.

Since the project I've been working for several years has become quite big, there are tens of places where a view controller is presented. The new presentation style doesn't always match our app designs and sometimes it causes the UI to fall apart. Which is why, we deciced to change UIViewController.modalPresentationStyle back to UIModalPresentationFullScreen as it was is pre-iOS13 SDK's versions.

但是在每个出现控制器的地方,在调用presentViewController:animated:completion:之前添加viewController.modalPresentationStyle = UIModalPresentationFullScreen似乎是过大的选择.而且,那时我们还有更严重的事情要处理,这就是为什么暂时或至少在我们更新设计并解决所有UI问题之前,我们决定采用方法混淆方法的原因.

But adding viewController.modalPresentationStyle = UIModalPresentationFullScreen before calling presentViewController:animated:completion: in every single place where a controller is presented seemed like an overkill. Moreover, we had more serious matters to deal with at that time, which is why, for the time being or at least until we update our designs and fix all the UI issues, we decided to go with method swizzling approach.

答案中提供了可行的解决方案,但是希望您能收到任何反馈,告诉我这种方法可能带来的负面影响或后果.

推荐答案

以下是我们通过使用swizzling方法实现的方法:

Objective-C

UIViewController + iOS13Fixes.h

UIViewController+iOS13Fixes.h

#import <Foundation/Foundation.h>

@interface UIViewController (iOS13Fixes)
@end

UIViewController + iOS13Fixes.m

UIViewController+ iOS13Fixes.m

#import <objc/runtime.h>

@implementation UIViewController (iOS13Fixes)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        SEL originalSelector = @selector(presentViewController:animated:completion:);
        SEL swizzledSelector = @selector(swizzled_presentViewController:animated:completion:);

        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

        BOOL methodExists = !class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));

        if (methodExists) {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        } else {
            class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
        }
    });
}

- (void)swizzled_presentViewController:(nonnull UIViewController *)viewController animated:(BOOL)animated completion:(void (^)())completion {

    if (@available(iOS 13.0, *)) {
        if (viewController.modalPresentationStyle == UIModalPresentationAutomatic || viewController.modalPresentationStyle == UIModalPresentationPageSheet) {
            viewController.modalPresentationStyle = UIModalPresentationFullScreen;
        }
    }

    [self swizzled_presentViewController:viewController animated:animated completion:completion];
}

@end


快速

UIViewController + iOS13Fixes.swift

UIViewController+iOS13Fixes.swift

import UIKit

@objc public extension UIViewController {

    private func swizzled_present(_ viewControllerToPresent: UIViewController, animated: Bool, completion: (() -> Void)?) {

        if #available(iOS 13.0, *) {
            if viewControllerToPresent.modalPresentationStyle == .automatic || viewControllerToPresent.modalPresentationStyle == .pageSheet {
                viewControllerToPresent.modalPresentationStyle = .fullScreen
            }
        }

        self.swizzled_present(viewControllerToPresent, animated: animated, completion: completion)
    }

    @nonobjc private static let _swizzlePresentationStyle: Void = {
        let instance: UIViewController = UIViewController()
        let aClass: AnyClass! = object_getClass(instance)

        let originalSelector = #selector(UIViewController.present(_:animated:completion:))
        let swizzledSelector = #selector(UIViewController.swizzled_present(_:animated:completion:))

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

        if let originalMethod = originalMethod, let swizzledMethod = swizzledMethod {
            if !class_addMethod(aClass, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)) {
                method_exchangeImplementations(originalMethod, swizzledMethod)
            } else {
                class_replaceMethod(aClass, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
            }
        }
    }()

    @objc static func swizzlePresentationStyle() {
        _ = self._swizzlePresentationStyle
    }
}

AppDelegate中的application:didFinishLaunchingWithOptions:中,通过调用(仅用于swift版本)来调用swizzling:

and in AppDelegate, in application:didFinishLaunchingWithOptions: invoke the swizzling by calling (swift version only):

UIViewController.swizzlePresentationStyle()

确保只调用一次(使用dispatch_once或类似的方法).

Make sure it's called only once (use dispatch_once or some equivalent).

有关在此处混乱的方法的更多信息:

More on method swizzling here:

  • https://nshipster.com/method-swizzling/
  • https://nshipster.com/swift-objc-runtime/
  • https://medium.com/rocknnull/ios-to-swizzle-or-not-to-swizzle-f8b0ed4a1ce6

这篇关于使用方法刷新在iOS13上的所有UIViewController实例上一次更改modalPresentationStyle的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-23 05:12