GitHub传送门
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
@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
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并且拖入到项目中,就可以了。