工程在Xcode11上編譯失敗的一些報錯,自行修改即可,大部分情況應該是代碼不夠規范導致的。至于這里,則主要總結下工程在Xcode11上正常編譯后,在iOS13系統手機上的一些問題。
問題一:
使用UITextField時,它的私有屬性_placeholderLabel被禁止訪問了
[_textField setValue:[UIFont boldSystemFontOfSize:14] forKeyPath:@"_placeholderLabel.font"];
在Xcode11上運行上述代碼會崩潰,崩潰信息如下:
reason: 'Access to UITextField's _placeholderLabel ivar is prohibited. This is an application bug'
iOS 13 通過 KVC 方式修改私有屬性,有 Crash 風險,需謹慎使用!并不是所有KVC都會Crash,要嘗試!
刪除上述方法中@"_placeholderLabel.font"里的“_”,程序可以正常工作,但是不建議這樣做。
解決措施1,通過以下方法實現對placeholder屬性的設置:
_textField.attributedPlaceholder = [[NSAttributedString alloc]initWithString:NSLocalizedString(@"請輸入關鍵字", nil) attributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:14], NSForegroundColorAttributeName:HexString(@"#A6A6A6")}];
解決措施2,需要添加頭文件#import <objc/runtime.h>
Ivar ivar = class_getInstanceVariable([UITextField class], "_placeholderLabel");
UILabel*placeholderLabel =object_getIvar(_textField, ivar);
placeholderLabel.textColor= [UIColorredColor];
問題二:
通過presentViewController彈出的模態控制器,彈出方式及效果和iOS13以前不同,這是因為UIViewController里的一個屬性modalPresentationStyle的默認值發生了改變。在iOS13之前,這個屬性的默認值是UIModalPresentationFullScreen,而在iOS13之后,默認值變成了UIModalPresentationAutomatic。和Xcode無關,只和iOS系統有關。
當然,嚴格意義上來說,這也不能算是一個問題,如果不能接受新的彈出效果,則只需要將控制器的modalPresentationStyle屬性設置下即可。為避免一處處去修改,我們可以通過UIViewController分類、重寫presentViewController等方式去實現。
問題三:
MPMoviePlayerController已經被棄用,在Xcode11上會Crash,信息如下:
reason: 'MPMoviePlayerController is no longer available. Use AVPlayerViewController in AVKit.'
解決措施:需要使用AVKit框架里的AVPlayerViewController來替代
問題四:
LaunchImage即將廢棄,得使用LaunchScreen來進行替換
從 iOS 8 的時候,蘋果就引入了 LaunchScreen,我們可以設置 LaunchScreen來作為啟動頁。當然,現在你還可以使用LaunchImage來設置啟動圖。不過使用LaunchImage的話,要求我們必須提供各種屏幕尺寸的啟動圖,來適配各種設備,隨著蘋果設備尺寸越來越多,這種方式顯然不夠 Flexible。而使用 LaunchScreen的話,情況會變的很簡單, LaunchScreen是支持AutoLayout+SizeClass的,所以適配各種屏幕都不在話下。
注意啦?,從2020年4月開始,所有使? iOS13 SDK的 App將必須提供 LaunchScreen,LaunchImage即將退出歷史舞臺
同時我們也可以看到,在Xcode11上,已經沒有了LaunchImage的選項:
如何使用LaunchScreen適配各種機型的手機?
如果單純使用一張啟動圖,是無法適配各種機型的,因為同一張圖在不同機型上可能會被拉伸變形。
因此,我們可以把一張啟動圖拆分開,拆成單獨的元素,在storyboard進行自動布局,這樣的話,就可以適配不同的機型、橫豎屏等情況了。
關于啟動頁實現、布局等內容具體可以參考一下鏈接:
啟動頁黑屏或白屏:http://www.lxweimin.com/p/d2b0f20e2e96
啟動頁強制豎屏,啟動后可以橫豎屏:https://www.coder4.com/archives/5406
使用Storyboard按比例自動布局技巧:https://blog.csdn.net/ws1352864983/article/details/52441938
問題五:
UIWindow,視圖層級發生了變化,如下圖,分別是Xcode11和Xcode11以前的版本下,UIWindow的視圖層級。
從上圖中,我們可以看到,UIWindow下的第一個子視圖不再是UILayoutContainerView,而是多出了UITransitionView、UIDropShadowView。
因此如果在iOS13上,我們如果想通過一下代碼獲取第一響應者,是獲取不到的
frontView = [[window subviews] objectAtIndex:0];
nextResponder = [frontView nextResponder];//iOS13上,獲取到的還是UIWindow(UITransitionView)
那么,如果我們在Xcode11下,還想要獲取到UILayoutContainerView怎么辦呢?可以通過類似下面的方式獲取到
? ? ? ? ? ? do {
? ? ? ? ? ? ? ? frontView = [[frontView subviews] objectAtIndex:0];
? ? ? ? ? ? } while ([frontView isKindOfClass:[UIView class]] && ![[frontView nextResponder] isKindOfClass:[UIViewController class]]);
問題六:
[[UIApplication sharedApplication] keyWindow] 方法即將被廢棄,被標記為API_DEPRECATED
我們可以看下官方描述:
@property(nullable, nonatomic,readonly) UIWindow *keyWindow API_DEPRECATED("Should not be used for applications that support multiple scenes as it returns a key window across all connected scenes", ios(2.0, 13.0));
官方描述的意思是,不應用于在返回時支持多個場景的應用程序。而如果我們的程序只支持單一場景的話,
我們可以在Xcode11上分別獲取keywindow、windows里的subwindow來打印看看
test window ++++ keywindow :<UIWindow: 0x109600ec0; frame = (0 0; 834 1194); autoresize = W+H; gestureRecognizers = <NSArray: 0x283793f90>; layer = <UIWindowLayer: 0x2839ca8a0>>
test window --- subwindow :<UIWindow: 0x109600ec0; frame = (0 0; 834 1194); autoresize = W+H; gestureRecognizers = <NSArray: 0x283793f90>; layer = <UIWindowLayer: 0x2839ca8a0>>
test window --- subwindow :<UITextEffectsWindow: 0x10964b680; frame = (0 0; 834 1194); opaque = NO; autoresize = W+H; layer = <UIWindowLayer: 0x28399a620>>
可以得出結論,對于這種只支持單一場景的應用來說,可以使用[[[UIApplication sharedApplication] windows] objectAtIndex:0]來替換keywindow的方法。
tips:至于UITextEffectsWindow是什么東西,可以看這個
問題七:
WKWebView?中測量頁面內容高度的方式變更如下
iOS 13以前 document.body.scrollHeight?
iOS 13中 document.documentElement.scrollHeight 兩者相差55 應該是瀏覽器定義高度變了
問題八:
暗黑模式,若當前需要屏蔽暗黑模式,則需要在plist文件中增加一下配置項即可:
<key>UIUserInterfaceStyle</key>
<string>Light</string>
問題九:
presentViewController子線程執行時,會引發Crash,必須在主線程執行。
通常來說,大家都知道,UI操作必須放到主線程中執行,但是,在Xcode11以前,我們在使用presentViewController時,在子線程也可以正常使用,我們在器block中打印,發現已經回到了主線程。可以猜測,如果在子線程中使用presentViewController,系統會強制將其拉回到主線程中執行,所以不會引發異常。
但是,使用Xcode11后,在子線程使用presentViewController,會直接引發Crash,
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'threading violation: expected the main thread'
所以,切記,一切的UI操作都要放到主線執行。
參考鏈接:
https://www.jb51.net/article/169852.htm