सभी UIViewController उदाहरणों में iOS13 पर modalPresentationStyle बदलें, एक बार विधि का उपयोग करते हुए स्विज़लिंग


11

[क्यू एंड ए] क्या UIViewController.modalPresentationStyleआईओएस १३ पर विश्व स्तर पर मूल्य बदलना संभव है इसलिए यह ऐसा व्यवहार करता है जैसा कि आईओएस १२ (या पहले) पर इस्तेमाल किया गया था?


क्यों?

आईओएस 13 एसडीके में का डिफ़ॉल्ट मान UIViewController.modalPresentationStyleसंपत्ति से बदल दिया गया है UIModalPresentationFullScreenकरने के लिए UIModalPresentationAutomaticजो है, जहाँ तक मुझे पता है, का संकल्प लिया UIModalPresentationPageSheetiOS उपकरणों या iPhones पर कम से कम।

चूंकि मैं जिस परियोजना पर कई वर्षों से काम कर रहा था वह काफी बड़ी हो गई है, वहाँ दसियों स्थान हैं जहाँ एक दृश्य नियंत्रक प्रस्तुत किया गया है। नई प्रस्तुति शैली हमेशा हमारे ऐप डिज़ाइन से मेल नहीं खाती है और कभी-कभी यह यूआई को अलग करने का कारण बनती है। यही कारण है कि, हमने पूर्व- iOS13 एसडीके संस्करणों के रूप में UIViewController.modalPresentationStyleवापस बदलने का UIModalPresentationFullScreenफैसला किया।

लेकिन हर एक जगह पर viewController.modalPresentationStyle = UIModalPresentationFullScreenकॉल करने से पहले जोड़ना presentViewController:animated:completion:जहां एक नियंत्रक प्रस्तुत किया जाता है, एक ओवरकिल की तरह लगता है। इसके अलावा, हमारे पास उस समय से निपटने के लिए अधिक गंभीर मामले थे, यही कारण है कि, इस समय तक या कम से कम जब तक हम अपने डिजाइनों को अपडेट नहीं करते हैं और सभी यूआई मुद्दों को ठीक करते हैं, हमने विधि स्विज़लिंग दृष्टिकोण के साथ जाने का फैसला किया।

कार्य समाधान मेरे उत्तर में प्रस्तुत किया गया है, लेकिन मैं किसी भी प्रतिक्रिया की सराहना करूँगा जो मुझे बताएगी कि इस तरह के दृष्टिकोण के क्या परिणाम या परिणाम हो सकते हैं।

जवाबों:


12

यहां बताया गया है कि हमने किस तरह से स्विज़लिंग का उपयोग करके यह हासिल किया:


उद्देश्य सी

UIViewController + iOS13Fixes.h

#import <Foundation/Foundation.h>

@interface UIViewController (iOS13Fixes)
@end

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

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:कॉल करके स्विज़लिंग को आमंत्रित करें (केवल स्विफ्ट संस्करण):

UIViewController.swizzlePresentationStyle()

सुनिश्चित करें कि इसे केवल एक बार (उपयोग dispatch_onceया कुछ समकक्ष) कहा जाता है ।


अधिक विधि यहाँ swizzling पर:


1
एक समस्या एक iPad पर चल रही होगी जहां आप वास्तव में एक पेज शीट चाहते हैं और पूर्ण स्क्रीन नहीं। आप अपने चेक को केवल पूर्ण स्क्रीन पर स्वचालित रूप से बदलने के लिए अद्यतन करना चाहते हैं और केवल तब ही कर सकते हैं जब प्रस्तुत दृश्य नियंत्रक में कॉम्पैक्ट चौड़ाई लक्षण होते हैं।
असभ्य

क्या यह समाधान अच्छा है? क्या होगा अगर कोई वास्तव में एक .Craft के रूप में ViewController पेश करना चाहता है?
ibrahimyilmaz

1
@ibrahimyilmaz तो आप सेट viewController.modalPresentationStyleकरने के लिए .pageSheetऔर कॉल self.swizzled_present(:,:,:)। शायद यह बहुत सुंदर नहीं है, लेकिन इस पोस्ट का पूरा बिंदु इस धारणा पर आधारित था कि आपके पास पहले से ही एक मौजूदा परियोजना है जिसमें बहुत सारी मोडल प्रस्तुति हैं और आप कोड की प्रत्येक पंक्ति को अपडेट किए बिना प्री-iOS13 व्यवहार को पुनर्स्थापित करना चाहते हैं।
bevoy
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.