最近更新了新系統,發現Modal樣式設置的UIModalPresentationFullScreen失效了。
相信大家在適配iOS13 系統的時候,為了適配Modal默認樣式發生變化( iOS13之前默認為UIModalPresentationFullScreen 13之后變為UIModalPresentationAutomatic)很多人是通過分類方法實現的。
即:為UIViewController擴展該方法(本質是重寫modalPresentationStyle屬性的get方法),這樣所有地方就直接生效了,不用一處一處修改,當然私有pod庫中的還是要自己修改。
/* Defines the presentation style that will be used for this view controller when it is presented modally. Set this property on the view controller to be presented, not the presenter. If this property has been set to UIModalPresentationAutomatic, reading it will always return a concrete presentation style. By default UIViewController resolves UIModalPresentationAutomatic to UIModalPresentationPageSheet, but system-provided subclasses may resolve UIModalPresentationAutomatic to other concrete presentation styles. Participation in the resolution of UIModalPresentationAutomatic is reserved for system-provided view controllers. Defaults to UIModalPresentationAutomatic on iOS starting in iOS 13.0, and UIModalPresentationFullScreen on previous versions. Defaults to UIModalPresentationFullScreen on all other platforms. */ @property(nonatomic,assign) UIModalPresentationStyle modalPresentationStyle API_AVAILABLE(ios(3.2));
// 適配iOS13 - (UIModalPresentationStyle)modalPresentationStyle { // 適配iOS13系統下 RN彈窗內容被遮擋 if ([self isKindOfClass:NSClassFromString(@"RCTModalHostViewController")]) { return UIModalPresentationOverCurrentContext; } else { return UIModalPresentationFullScreen; } }
然后問題來了,分類中的 - (UIModalPresentationStyle)modalPresentationStyle 這個方法在Xcode 11.4 & iOS 13.4 環境下 不再執行了。
至此找到問題根本原因是 Xcode 11.4 & iOS 13.4 環境下 分類重寫系統級屬性的get方法會失效。正常的系統級方法(如:- (void)viewWillAppear:(BOOL)animated;重寫)還是會調用。
解決辦法:(目前最高效辦法是1,若后續蘋果不修復此BUG,可用方法2解決)
1、使用低版本Xcode打包
2、使用運行時方法替換(系統還是會調用這個方法,只不過不再調用我們重寫的get方法,所以替換方法實現)
+ (void)swizzleInstanceSelector:(SEL)originalSelector withSelector:(SEL)swizzledSelector { Class class = [self class]; Method originalMethod = class_getInstanceMethod(class, originalSelector); Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); BOOL success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); if (success) { class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); } else { method_exchangeImplementations(originalMethod, swizzledMethod); } } + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ [self swizzleInstanceSelector:@selector(modalPresentationStyle) withSelector:@selector(uiviewController_modalPresentationStyle)]; }); } - (UIModalPresentationStyle)uiviewController_modalPresentationStyle { // 適配iOS13系統下 RN彈窗內容被遮擋 if ([self isKindOfClass:NSClassFromString(@"RCTModalHostViewController")]) { return UIModalPresentationOverCurrentContext; } else { return UIModalPresentationFullScreen; } }
拓展:
系統屬性的get方法重寫可能都會受到影響