對於開發者來說 iOS13做了些許變更 現在簡介下自己在項目中遇到的問題,可能不全面,只是遇到的問題及處理辦法
一、Modal默認樣式發生變化 iOS13之前默認為UIModalPresentationFullScreen 13之后變為UIModalPresentationAutomatic
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, };
適配方法:
1、明確指定控制器的modalPresentationStyle為UIModalPresentationFullScreen;
cameraController.modalPresentationStyle = UIModalPresentationFullScreen;
2、為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;
}
}
二、部分私有API結構發生變化,之前的訪問方式會導致崩潰
項目中我們一直會通過KVC去修改系統中的私有API的一些屬性,比如獲取搜索框的_searchField修改色值字體等等,在iOS13之后這樣是不被允許的,用xocde11打包在iOS13系統下直接會崩潰。
適配方法:
1、用低版本xcode打包(xocde11以下版本),這樣在iOS13系統下是不會崩潰的,但是不建議這么做
2、不再訪問私有屬性
_searchField 獲取方式
iOS13對外暴露了searchTextField 屬性 直接獲取就行
@interface UISearchBar (UITokenSearch) @property (nonatomic, readonly) UISearchTextField *searchTextField; @end
UITextField *searchTextField; if (@available(iOS 13.0, *)) { searchTextField = searchBar.searchTextField; }else { searchTextField = [searchBar valueForKey:@"_searchField"]; }
StatusBar 獲取方式
UIView *statusBar = [UIView new]; if (@available(iOS 13.0, *)) { statusBar = [[UIView alloc] initWithFrame:[UIApplication sharedApplication].statusBarFrame]; [[UIApplication sharedApplication].keyWindow addSubview:statusBar]; } else { statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"]; }
三、PHPhotoLibrary 的performChanges 與 performChangesAndWait 方法
先說我遇到的問題:我是先拍照然后保存到相冊,在iOS13之前使用performChanges這個方法能夠正常,但在iOS13之后發現保存到相冊后回調失效,導致的效果就是拍攝后卡到那里沒反應。
一般我們在操作到相冊的時候回用到這個類,比如存儲照片或者視頻到相冊之類的。第一個方法是異步操作,第二個方法是同步操作。在iOS13之前使用performChanges是沒有問題的,可以在回調中做相關操作,但在iOS13之后回調會不好使,所以必須在performChangesAndWait之后做相關操作。
// handlers are invoked on an arbitrary serial queue // Nesting change requests will throw an exception - (void)performChanges:(dispatch_block_t)changeBlock completionHandler:(nullable void(^)(BOOL success, NSError *__nullable error))completionHandler; - (BOOL)performChangesAndWait:(dispatch_block_t)changeBlock error:(NSError *__autoreleasing *)error;
適配方法:
將performChanges方法替換為performChangesAndWait方法,同時將performChanges回調中的操作放到performChangesAndWait執行之后
四、UIWebView將廢棄
大家對UIWebView都是有情懷的,之前在iOS8的時候引入WebKit框架提供WKWebView,性能較UIWebView有很大的提升,但也改變了很多,比如UIWebView是通過外聯協議實現事件交互,但WKWebView是通過消息機制實現的,我廠一直未替換的原因就在於此,但這把看來蘋果是鐵了心要讓大家替換了,所以就用WKWebView吧
UIKIT_EXTERN API_DEPRECATED("No longer supported; please adopt WKWebView.", ios(2.0, 12.0)) API_UNAVAILABLE(tvos, macos) @interface UIWebView : UIView <NSCoding, UIScrollViewDelegate>
#if TARGET_OS_IPHONE WK_EXTERN API_AVAILABLE(macos(10.10), ios(8.0)) @interface WKWebView : UIView #else WK_EXTERN API_AVAILABLE(macos(10.10), ios(8.0)) @interface WKWebView : NSView #endif
適配方法:
使用WKWebView代替,但如果涉及到與原生事件交互的話,可能需要點工作量,但這是趨勢。
五、暗黑模式
將同一個資源,創建出兩種模式的樣式。系統根據當前選擇的樣式,自動獲取該樣式的資源。
每次系統更新樣式時,應用會調用當前所有存在的元素調用對應的一些重新方法,進行重繪視圖,可以在對應的方法做相應的改動。
適配方法:
1、適配暗黑模式
1-1、創建一個Assets文件(或在現有的Assets文件中)
1-2、新建一個圖片資源文件(或者顏色資源文件、或者其他資源文件)
1-3、選中該資源文件, 打開 Xcode ->View ->Inspectors ->Show Attributes Inspectors (或者Option+Command+4)視圖,將Apperances 選項 改為Any,Dark
1-4、執行完第三步,資源文件將會有多個容器框,分別為 Any Apperance 和 Dark Apperance. Any Apperance 應用於默認情況(Unspecified)與高亮情況(Light), Dark Apperance 應用於暗黑模式(Dark)
1-5、代碼默認執行時,就可以正常通過名字使用了,系統會根據當前模式自動獲取對應的資源文件
2、關閉暗黑模式
2-1、配置plist文件: 在Info.plist 文件中,添加UIUserInterfaceStyle key 名字為 User Interface Style 值為String,將UIUserInterfaceStyle key 的值設置為 Light。
2-2、代碼關閉黑暗模式 強制關閉暗黑模式
#if defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0 if(@available(iOS 13.0,*)){ self.window.overrideUserInterfaceStyle = UIUserInterfaceStyleLight; } #endif
六、UISegmentedControl發生變化
UISegmentedControl iOS13之前默認選中樣式是帶邊框、且選中是藍色的、只能點擊選中。iOS13之后 默認是無邊框、且字體色值變為灰色、且可以滑動選中
適配方法:
// 設置默認選中色值 [segmentedControl setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:ICOME_COLOR_3480FF, NSForegroundColorAttributeName,[UIFont boldSystemFontOfSize:15.0f],NSFontAttributeName, nil] forState:UIControlStateSelected]; // 添加邊框 [segmentedControl borderWidth:1 andBorderColor:[UIColor whiteColor]];
-(instancetype)borderWidth:(CGFloat)borderWidth andBorderColor:(UIColor*)borderColor
{
CALayer* layer=self.layer;
layer.borderWidth=borderWidth;
layer.borderColor=borderColor.CGColor;
return self;
}
