Making portal

The presentViewController style is the default in iOS13

This style obviously doesn’t fit our UI, and the problem is that we’ve been ignoring the UIModalPresentationStyle property.

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));Copy the code

Before iOS13 versions, UIViewController UIModalPresentationStyle attribute is the default UIModalPresentationFullScreen, In the iOS13 UIModalPresentationPageSheet. So we need to set the UIModalPresentationStyle on the presentViewController to get the old effect.

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

One more thing

If you set modalPresentationStyle at every presentViewController, obviously that’s not Cool enough. So here’s the idea.

Create a Category of UIViewController in your project and put the following section in.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(@ the 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
Copy the code

At this point you can implement the old PresentViewController style, but you can’t handle a particular OR a class of UIViewControllers to avoid automatically setting the modalPresentationStyle, so here’s the solution.

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
Copy the code

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(@ the 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
Copy the code

Another thing

Of course, there’s an easier way to just download UIViewController+LLUtils and drag it into your project.