美文网首页iOS开发杂货铺
iOS13 [UIViewController presentV

iOS13 [UIViewController presentV

作者: HDB_Li | 来源:发表于2019-08-23 15:31 被阅读0次

    GitHub传送门

    iOS13默认的presentViewController样式


    iOS13默认的presentViewController样式

    这种样式显然不能符合我们UI的要求,产生这样的问题是因为我们之前一直忽略了UIModalPresentationStyle这个属性。

    typedef NS_ENUM(NSInteger, UIModalPresentationStyle) {
        UIModalPresentationFullScreen = 0,
        UIModalPresentationPageSheet API_AVAILABLE(ios(3.2)) API_UNAVAILABLE(tvos),
        UIModalPresentationFormSheet API_AVAILABLE(ios(3.2)) API_UNAVAILABLE(tvos),
        UIModalPresentationCurrentContext API_AVAILABLE(ios(3.2)),
        UIModalPresentationCustom API_AVAILABLE(ios(7.0)),
        UIModalPresentationOverFullScreen API_AVAILABLE(ios(8.0)),
        UIModalPresentationOverCurrentContext API_AVAILABLE(ios(8.0)),
        UIModalPresentationPopover API_AVAILABLE(ios(8.0)) API_UNAVAILABLE(tvos),
        UIModalPresentationBlurOverFullScreen API_AVAILABLE(tvos(11.0)) API_UNAVAILABLE(ios) API_UNAVAILABLE(watchos),
        UIModalPresentationNone API_AVAILABLE(ios(7.0)) = -1,
        UIModalPresentationAutomatic API_AVAILABLE(ios(13.0)) = -2,
    };
    
    @property(nonatomic,assign) UIModalPresentationStyle modalPresentationStyle API_AVAILABLE(ios(3.2));
    

    在iOS13之前的版本中, UIViewController的UIModalPresentationStyle属性默认是UIModalPresentationFullScreen,而在iOS13中变成了UIModalPresentationPageSheet
    所以我们需要在presentViewController时,设置一下UIModalPresentationStyle,就可以达到旧的效果。

        UIViewController *viewController = [[UIViewController alloc] init];
        viewController.modalPresentationStyle = UIModalPresentationFullScreen;
        [self persentViewController:viewController animated:YES completion:nil];
    

    One more thing

    如果在每一处presentViewController都设置modalPresentationStyle,显然这不够Cool。所以就有下面的思路。

    在项目中创建UIViewController的Category,并且在.m中写入如下部分

    #import "UIViewController+LL_Utils.h"
    #import <objc/runtime.h>
    
    @implementation UIViewController (Utils)
    
    + (void)load {
        Method originAddObserverMethod = class_getInstanceMethod(self, @selector(presentViewController:animated:completion:));
        Method swizzledAddObserverMethod = class_getInstanceMethod(self, @selector(LL_presentViewController:animated:completion:));
        method_exchangeImplementations(originAddObserverMethod, swizzledAddObserverMethod);
    }
    
    - (void)LL_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
        if (@available(iOS 13.0, *)) {
            viewControllerToPresent.modalPresentationStyle = UIModalPresentationFullScreen;
            [self LL_presentViewController:viewControllerToPresent animated:flag completion:completion];
        } else {
            // Fallback on earlier versions
            [self LL_presentViewController:viewControllerToPresent animated:flag completion:completion];
        }
    }
    @end
    

    到这里已经可以实现旧的PresentViewController的样式,但是不能处理某个或者某类UIViewController避免自动设置modalPresentationStyle,所以就有了下面这个方案。

    UIViewController+LL_Utils.h

    @interface UIViewController (LL_Utils)
    
    /**
    Whether or not to set ModelPresentationStyle automatically for instance, Default is [Class LL_automaticallySetModalPresentationStyle].
    
    @return BOOL
    */
    @property (nonatomic, assign) BOOL LL_automaticallySetModalPresentationStyle;
    
    /**
     Whether or not to set ModelPresentationStyle automatically, Default is YES, but UIImagePickerController/UIAlertController is NO.
    
     @return BOOL
     */
    + (BOOL)LL_automaticallySetModalPresentationStyle;
    
    @end
    

    UIViewController+LL_Utils.m

    #import "UIViewController+LL_Utils.h"
    #import <objc/runtime.h>
    
    static const char *LL_automaticallySetModalPresentationStyleKey;
    
    @implementation UIViewController (LL_Utils)
    
    + (void)load {
        Method originAddObserverMethod = class_getInstanceMethod(self, @selector(presentViewController:animated:completion:));
        Method swizzledAddObserverMethod = class_getInstanceMethod(self, @selector(LL_presentViewController:animated:completion:));
        method_exchangeImplementations(originAddObserverMethod, swizzledAddObserverMethod);
    }
    
    - (void)setLL_automaticallySetModalPresentationStyle:(BOOL)LL_automaticallySetModalPresentationStyle {
        objc_setAssociatedObject(self, LL_automaticallySetModalPresentationStyleKey, @(LL_automaticallySetModalPresentationStyle), OBJC_ASSOCIATION_ASSIGN);
    }
    
    - (BOOL)LL_automaticallySetModalPresentationStyle {
        id obj = objc_getAssociatedObject(self, LL_automaticallySetModalPresentationStyleKey);
        if (obj) {
            return [obj boolValue];
        }
        return [self.class LL_automaticallySetModalPresentationStyle];
    }
    
    + (BOOL)LL_automaticallySetModalPresentationStyle {
        if ([self isKindOfClass:[UIImagePickerController class]] || [self isKindOfClass:[UIAlertController class]]) {
            return NO;
        }
        return YES;
    }
    
    - (void)LL_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
        if (@available(iOS 13.0, *)) {
            if (viewControllerToPresent.LL_automaticallySetModalPresentationStyle) {
                viewControllerToPresent.modalPresentationStyle = UIModalPresentationFullScreen;
            }
            [self LL_presentViewController:viewControllerToPresent animated:flag completion:completion];
        } else {
            // Fallback on earlier versions
            [self LL_presentViewController:viewControllerToPresent animated:flag completion:completion];
        }
    }
    
    @end
    

    Another thing

    当然还有一个更简单的方法,直接下载UIViewController+LLUtils并且拖入到项目中,就可以了。

    相关文章

      网友评论

        本文标题:iOS13 [UIViewController presentV

        本文链接:https://www.haomeiwen.com/subject/svmzsctx.html