出现这个问题主要因为 iOS以后,模态出来的viewcontroller中 modalPresentationStyle的默认值改变了,
iOS 13之前,modalPresentationStyle值默认为:UIModalPresentationFullScreen
在iOS 13中,modalPresentationStyle默认值为:UIModalPresentationAutomatic
修改要模态viewcontroller的modalPresentationStyle为:UIModalPresentationFullScreen 就就可以填充全屏
后果:被怼了很惨,因为项目里有很多模态出来的VC是半透明,结果现在变成完全不透明,背景为黑色。
解决方法1:
挨个修改VC 的modalPresentationStyle;代码多不说,漏改是大事,万一以后还有很多是半透密的,每次都要写,烦…………
解决方法2:
利用OC的runtime机制,交换系统方法:presentViewController:animated:completion:
具体实现如下:
在基类的.m中 做交换
#import <objc/runtime.h>
+ (void)load{
// 适配ios 13 这里做方法交换
static dispatch_once_tonceToken;
dispatch_once(&onceToken, ^{
// 系统模态方法, 做方法交换
Method systemPresent =class_getInstanceMethod(self,@selector(presentViewController:animated:completion:));
Method custom_Method =class_getInstanceMethod(self,@selector(xbPresentViewController:animated:completion:));
method_exchangeImplementations(systemPresent, custom_Method);
});
}
- (void)xbPresentViewController:(UIViewController*)viewControllerToPresentanimated:(BOOL)flag completion:(void(^)(void))completion {
//设置满屏,可以半透明
if(@available(iOS13.0, *)) {
viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverFullScreen;
}
[self xbPresentViewController:viewControllerToPresentanimated:flagcompletion:completion];
}
后遗症:因为把显示效果修改为:UIModalPresentationOverFullScreen;半透明,全屏覆盖的问题都得到完美解决。但是会引发一个新的问题:前一个页面的viewWillAppear:、viewDidAppear:也无法触发。例如: A Present B, 有时因为业务逻辑需要,必须在viewWillAppear, viewDidAppear里写一些代码,当B 调用dismiss方法的时候, A的这个两个方法不会触发,因此会有一些安全隐患。因此如果要求B 调用dismiss方法,A要执行viewWillAppear:、viewDidAppear:这个两个方法,这个时候要把B的modalPresentationStyle设置为:UIModalPresentationFullScreen;
方法改进:
- (void)myPresentViewController:(UIViewController*)viewControllerToPresentanimated:(BOOL)flagcompletion:(void(^)(void))completion {
//设置满屏,可以半透明
if(@available(iOS13.0, *)) {
if([viewControllerToPresent isKindOfClass:[YourViewController class]]) {
viewControllerToPresent.modalPresentationStyle = UIModalPresentationFullScreen;
} else {
viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverFullScreen;
}
}
[self myPresentViewController:viewControllerToPresentanimated:flagcompletion:completion];
}
其他:如果要求 B既要半透明,dismiss时,A还要调用viewWillAppear:、viewDidAppear:。我的想法是在B 写一个block,在B调用dismiss之前,利用block回调A相关的业务逻辑代码。如果有其他更好的方法请告诉我。万分感谢!!
网友评论