iOS13適配

隨著iPhone 11的發(fā)布惭载,iOS 13適配也提上了日程来惧,剛好最近在做項(xiàng)目適配,順便總結(jié)一下:
首先升級(jí)Xcode11摹迷,iOS13版本,因?yàn)閄code11出現(xiàn)了一些新的API郊供。廢話不多說(shuō)峡碉,直接上菜:

一、私有KVC

在iOS13中驮审,不在允許通過(guò)KVC的方式去訪問(wèn)私有屬性鲫寄,需要通過(guò)其他方式去修改吉执;之前如果使用到,會(huì)造成崩潰地来。

在網(wǎng)上看到有人說(shuō) 私有KVC崩潰與系統(tǒng)版本無(wú)關(guān)戳玫,與Xcode版本有關(guān),Xcode11編譯會(huì)崩潰未斑。
我個(gè)人覺(jué)得這個(gè)說(shuō)法是錯(cuò)的咕宿;通過(guò)我的驗(yàn)證,我認(rèn)為私有KVC在Xcode11---iOS12以下的系統(tǒng)不會(huì)崩潰蜡秽,Xcode11---iOS13的會(huì)崩潰府阀;大家也可以自己驗(yàn)證一下。

目前我找到的會(huì)觸發(fā) KVC 訪問(wèn)權(quán)限異常崩潰的方法有:

  • UITabBarButton -> _info
  • UITextField -> _placeholderLabel
  • _UIBarBackground -> _shadowView
  • _UIBarBackground -> _backgroundEffectView
  • UISearchBar -> _cancelButtonText
  • UISearchBar -> _cancelButton
  • UISearchBar -> _searchField

目前我項(xiàng)目中芽突,主要用到UITextFieldUISearchBar的私有屬性肌似,現(xiàn)在我就拿這兩個(gè)分析一下:

1、UITextFiled 修改根據(jù)kvc提示文字的大小和顏色诉瓦,

這樣寫:

[self.onePwdField setValue:color_cccccc forKeyPath:@"_placeholderLabel.textColor"];

在Xcode11--iOS13會(huì)直接崩潰,修改方法為:

self.onePwdField.attributedPlaceholder = [self placeholder:@"請(qǐng)輸入原來(lái)的密碼"];

-(NSMutableAttributedString *)placeholder:(NSString *)text{
    if (text.length == 0) {
        return nil;
    }
    NSMutableAttributedString *att = [[NSMutableAttributedString alloc]initWithString:text attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15],NSForegroundColorAttributeName:color_cccccc}];
    return att;
}
2力细、獲取UISearchBar的textField

在iOS13之前睬澡,我們通過(guò)"_searchField"來(lái)獲取UISearchTextField來(lái)修改一些屬性。

 UITextField *searchFiled = [self valueForKey:@"_searchField"];

在iOS13中,繼續(xù)這樣會(huì)崩潰眠蚂,修改方法為:

 UITextField *searchFiled;
 if(@available(iOS 13.0, *)) {
    searchFiled =  self.searchTextField; 
 }else{
    searchFiled = [self valueForKey:@"_searchField"];
 }
3煞聪、UISearchBar 黑線處理導(dǎo)致崩潰

iOS13之前為了處理搜索框的黑線問(wèn)題,通常會(huì)遍歷 searchBar 的 subViews逝慧,找到并刪除 UISearchBarBackground昔脯。
在 iOS13 中這么做會(huì)導(dǎo)致 UI 渲染失敗,然后直接崩潰笛臣,崩潰信息如下:

Terminating app due to uncaught exception'NSInternalInconsistencyException', reason: 'Missing or detached view for search bar layout'

修改方法為:設(shè)置 UISearchBarBackground 的 layer.contents 為 nil

 for (UIView *view in _searchBar.subviews.lastObject.subviews) {
   if ([view isKindOfClass:NSClassFromString(@"UISearchBarBackground")]) {
        view.layer.contents = nil;
        break;
    }
 } 
4云稚、 設(shè)置UISearchBar 的searchTextField.attributedPlaceholder無(wú)效問(wèn)題。

在 iOS13中需要把設(shè)置的代碼寫在viewDidAppear,親測(cè)可以.

5沈堡、獲取狀態(tài)欄視圖静陈,以下兩種方法在iOS13導(dǎo)致崩潰。
UIView *statusBar = [[UIApplication sharedApplication] valueForKey:@"statusBar"];
或:
UIView *statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];

改為:

if(@available(iOS 13.0, *)) {
        
}else{
    UIView *statusBar = [[UIApplication sharedApplication] valueForKey:@"statusBar"];
    statusBar.transform = CGAffineTransformIdentity;
}

二诞丽、presentViewController的問(wèn)題(模態(tài)彈出默認(rèn)樣式改變)

在 iOS 13鲸拥,使用 presentViewController 方式打開(kāi)視圖,會(huì)跟導(dǎo)航欄有部分視覺(jué)差僧免,這里就不上圖了刑赶,可以自行試一下。
原因是:蘋果將 UIViewControllermodalPresentationStyle 屬性的默認(rèn)值改成了新加的一個(gè)枚舉值 UIModalPresentationAutomatic懂衩,對(duì)于多數(shù) UIViewController撞叨,此值會(huì)映射成 UIModalPresentationPageSheet金踪。

  • 解決辦法: 可以在vc present之前設(shè)置modalPresentationStyle 為 UIModalPresentationFullScreen

  • 另外,present的vc用戶下拉可以dissmiss控制器谒所,如果不想要這效果热康,可以這樣設(shè)置

/*當(dāng)該屬性為 false 時(shí),用戶下拉可以 dismiss 控制器劣领,為 true 時(shí)姐军,下拉不可以 dismiss控制器*/

xxVC.isModalInPresentation = true;
  • 還有一點(diǎn)需要注意尖淘,原來(lái)以UIModalPresentationFullScreen樣式彈出頁(yè)面奕锌,那么這個(gè)頁(yè)面彈出 ViewController 會(huì)依次調(diào)viewWillDisappear和 viewDidDisappear。然后在這個(gè)頁(yè)面被 dismiss 的時(shí)候村生,將他彈出的那個(gè) ViewController 的 viewWillAppear 和 viewDidAppear會(huì)被依次調(diào)用惊暴。然而使用默認(rèn)的視差效果彈出頁(yè)面,將他彈出的那個(gè) ViewController 并不會(huì)調(diào)用這些方法趁桃,原先寫在這四個(gè)函數(shù)中的代碼以后都有可能會(huì)存在問(wèn)題辽话。

三、藍(lán)牙權(quán)限更新

在 iOS 13 中卫病,蘋果將原來(lái)藍(lán)牙申請(qǐng)權(quán)限用的 NSBluetoothPeripheralUsageDescription 字段油啤,替換為 NSBluetoothAlwaysUsageDescription 字段。

藍(lán)牙權(quán)限.png

四蟀苛、廢棄UIWebview 改用 WKWebView

iOS13 開(kāi)始蘋果將 UIWebview 列為過(guò)期API(支持iOS2.0-iOS12)益咬。 目前提交蘋果應(yīng)用市場(chǎng)(App Store)會(huì)發(fā)送郵件提示你在下一次提交時(shí)將應(yīng)用中UIWebView 的 api 移除。

暫時(shí)沒(méi)有強(qiáng)制使用WKWebView帜平,但是在iOS13開(kāi)始UIWebView已是廢棄的API幽告,以后更高的版本中防止出現(xiàn)問(wèn)題,盡早移除是上上之策裆甩。

五冗锁、UISegmentedControl 默認(rèn)樣式改變。

默認(rèn)樣式變?yōu)?白底黑字嗤栓,如果設(shè)置修改過(guò)顏色的話蒿讥,頁(yè)面需要修改。

六抛腕、WKWebView 中測(cè)量頁(yè)面內(nèi)容高度的方式變更

iOS 13以前 document.body.scrollHeight iOS 13中 document.documentElement.scrollHeight 兩者相差55 應(yīng)該是瀏覽器定義高度變了芋绸。

七、關(guān)于暗黑模式和切換

1担敌、暗黑模式是iOS13的一大亮點(diǎn)摔敛,下面來(lái)看看模式切換的設(shè)置
(1) 切換 修改當(dāng)前 UIViewController 或 UIView的模式。只要設(shè)置了控制器為暗黑模式全封,那么它子view也會(huì)對(duì)應(yīng)的修改马昙。

即:只會(huì)影響當(dāng)前的視圖桃犬,不會(huì)影響前面的 controller 和后續(xù) present 的 controller。

if (@available(iOS 13.0, *)) {
   self.overrideUserInterfaceStyle =  UIUserInterfaceStyleDark;//UIUserInterfaceStyleLight
} else {
        // Fallback on earlier versions
}

注意啦??行楞,但是當(dāng)我們?cè)?window 上設(shè)置 overrideUserInterfaceStyle 的時(shí)候攒暇,就會(huì)影響 window 下所有的 controller, view,包括后續(xù)推出的 controller子房。

(2) 獲取當(dāng)前的模式
if (@available(iOS 12.0, *)) {
     if (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ){
            // Dark
          NSLog(@"是dark模式形用、。证杭。田度。");
     } else  if (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleLight) {
            // Light
          NSLog(@"是light模式、解愤。镇饺。。");
     } else {
            //unspecified
          NSLog(@"是unspecified模式送讲、奸笤。。哼鬓。");
     }
}
(3) 監(jiān)聽(tīng)模式的變化
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
    [super traitCollectionDidChange:previousTraitCollection];
// trait發(fā)生了改變
    if (@available(iOS 13.0, *)) {
        if ([self.traitCollection hasDifferentColorAppearanceComparedToTraitCollection:previousTraitCollection]) {
            // 執(zhí)行操作
        }
    } else {
        // Fallback on earlier versions
    }
}
2揭保、適配暗黑模式
(1)將同一個(gè)資源,創(chuàng)建出兩種模式的樣式魄宏。系統(tǒng)根據(jù)當(dāng)前選擇的樣式,自動(dòng)獲取該樣式的資源
(2)每次系統(tǒng)更新樣式時(shí)存筏,應(yīng)用會(huì)調(diào)用當(dāng)前所有存在的元素調(diào)用對(duì)應(yīng)的一些重新方法宠互,進(jìn)行重繪視圖,可以在對(duì)應(yīng)的方法做相應(yīng)的改動(dòng)椭坚。
(3)資源文件適配
  • 1.創(chuàng)建一個(gè)Assets文件(或在現(xiàn)有的Assets文件中)
    詳情請(qǐng)看:iOS中創(chuàng)建多個(gè)Assets.xcassets文件
  • 2.新建一個(gè)圖片資源文件(或者顏色資源文件予跌、或者其他資源文件)
  • 3.選中該資源文件, 打開(kāi) Xcode ->View ->Inspectors ->Show Attributes Inspectors (或者Option+Command+4)視圖善茎,將Apperances 選項(xiàng) 改為Any券册,Dark
  • 4.執(zhí)行完第三步,資源文件將會(huì)有多個(gè)容器框垂涯,分別為 Any Apperance 和 Dark Apperance. Any Apperance 應(yīng)用于默認(rèn)情況(Unspecified)與高亮情況(Light)烁焙, Dark Apperance 應(yīng)用于暗黑模式(Dark)
  • 5.代碼默認(rèn)執(zhí)行時(shí),就可以正常通過(guò)名字使用了耕赘,系統(tǒng)會(huì)根據(jù)當(dāng)前模式自動(dòng)獲取對(duì)應(yīng)的資源文件

注意啦??骄蝇,同一工程內(nèi)多個(gè)Assets文件在打包后,就會(huì)生成一個(gè)Assets.car 文件操骡,所以要保證Assets內(nèi)資源文件的名字不能相同.

  • 步驟如圖:
    資源文件適配暗黑模式.png
資源文件適配暗黑模式.png
3九火、全局關(guān)閉黑暗模式
  • 方式一 配置plist文件: 在Info.plist 文件中赚窃,添加UIUserInterfaceStyle key 名字為 User Interface Style 值為String,將UIUserInterfaceStyle key 的值設(shè)置為 Light岔激。


    全局關(guān)閉黑暗模式.png

在開(kāi)發(fā)中勒极,如果用的系統(tǒng)控件(如cell、tableview的背景色)未設(shè)置背景色(或者為透明)虑鼎,則進(jìn)入暗黑模式后辱匿,控件背景色變?yōu)楹谏?/p>

可以每一個(gè)頁(yè)面設(shè)置,當(dāng)然也可以整體設(shè)置震叙, 一般我們的APP都是在一個(gè)window下的掀鹅,那就整體設(shè)置APP里的window

  • 方式二 :代碼關(guān)閉黑暗模式 強(qiáng)制關(guān)閉暗黑模式
#if defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
if(@available(iOS 13.0,*)){
    self.window.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
}
#endif
4、單個(gè)界面不遵循暗黑模式
  • UIViewController與UIView 都新增一個(gè)屬性 overrideUserInterfaceStyle
  • 將 overrideUserInterfaceStyle 設(shè)置為對(duì)應(yīng)的模式媒楼,則強(qiáng)制限制該元素與其子元素以設(shè)置的模式進(jìn)行展示乐尊,不跟隨系統(tǒng)模式改變進(jìn)行改變

1、設(shè)置 ViewController 的該屬性划址, 將會(huì)影響視圖控制器的視圖和子視圖控制器采用該樣式扔嵌。
2、設(shè)置 View 的該屬性夺颤, 將會(huì)影響視圖及其所有子視圖采用該樣式痢缎。
3、設(shè)置 Window 的該屬性世澜, 將會(huì)影響窗口中的所有內(nèi)容都采用樣式独旷,包括根視圖控制器和在該窗口中顯示內(nèi)容的所有演示控制器(UIPresentationController)

更詳細(xì)的暗黑模式設(shè)置請(qǐng)看:iOS適配暗黑模式

八、即將廢棄的 LaunchImage(iOS 7.0–13.0)

從 iOS 8 的時(shí)候寥裂,蘋果就引入了 LaunchScreen.storyboard嵌洼,我們可以設(shè)置 LaunchScreen來(lái)作為啟動(dòng)頁(yè)。當(dāng)然封恰,現(xiàn)在你還可以使用LaunchImage來(lái)設(shè)置啟動(dòng)圖麻养。不過(guò)使用LaunchImage的話,要求我們必須提供各種屏幕尺寸的啟動(dòng)圖诺舔,來(lái)適配各種設(shè)備鳖昌,隨著蘋果設(shè)備尺寸越來(lái)越多,這種方式顯然不夠 Flexible低飒。而使用 LaunchScreen的話许昨,情況會(huì)變的很簡(jiǎn)單, LaunchScreen是支持AutoLayout+SizeClass的褥赊,所以適配各種屏幕都不在話下车要。

注意啦??,從2020年4月開(kāi)始崭倘,所有使? iOS13 SDK 的 App 將必須提供 LaunchScreen.storyboard翼岁,LaunchImage即將退出歷史舞臺(tái)类垫,否則將無(wú)法提交到 App Store 進(jìn)行審批。

九琅坡、StatusBar 與之前版本不同

目前狀態(tài)欄也增加了一種模式悉患,由之前的兩種,變成了三種, 其中default由之前的黑色內(nèi)容榆俺,變成了會(huì)根據(jù)系統(tǒng)模式售躁,自動(dòng)選擇當(dāng)前展示lightContent還是darkContent。

十茴晋、iOS13 獲取window適配

    UIWindow* window = nil;
     
    if (@available(iOS 13.0, *)) {
        for (UIWindowScene* windowScene in [UIApplication sharedApplication].connectedScenes)
        {
           if (windowScene.activationState == UISceneActivationStateForegroundActive)
           {
                window = windowScene.windows.firstObject;
     
                break;
           }
        }
    }else{
        window = [UIApplication sharedApplication].keyWindow;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末陪捷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子诺擅,更是在濱河造成了極大的恐慌市袖,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烁涌,死亡現(xiàn)場(chǎng)離奇詭異苍碟,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)撮执,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門微峰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人抒钱,你說(shuō)我怎么就攤上這事蜓肆。” “怎么了谋币?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵仗扬,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我瑞信,道長(zhǎng),這世上最難降的妖魔是什么穴豫? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任凡简,我火速辦了婚禮,結(jié)果婚禮上精肃,老公的妹妹穿的比我還像新娘秤涩。我一直安慰自己,他們只是感情好司抱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布筐眷。 她就那樣靜靜地躺著,像睡著了一般习柠。 火紅的嫁衣襯著肌膚如雪匀谣。 梳的紋絲不亂的頭發(fā)上照棋,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音武翎,去河邊找鬼烈炭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛宝恶,可吹牛的內(nèi)容都是我干的符隙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼垫毙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼霹疫!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起综芥,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤丽蝎,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后毫痕,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體征峦,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年消请,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了栏笆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡臊泰,死狀恐怖蛉加,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情缸逃,我是刑警寧澤针饥,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站需频,受9級(jí)特大地震影響丁眼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜昭殉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一苞七、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧挪丢,春花似錦蹂风、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春撵渡,著一層夾襖步出監(jiān)牢的瞬間融柬,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工姥闭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留丹鸿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓棚品,卻偏偏與公主長(zhǎng)得像靠欢,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子铜跑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1.私有KVC [self setValue:baseTabBar forKey:@"tabBar"]; //正常...
    小和大大閱讀 795評(píng)論 0 1
  • 1.私有KVC 在Xcode10上編譯不會(huì)有問(wèn)題门怪,但是在Xcode11上編譯的會(huì)崩潰。并且- (void)setV...
    iOS亮子閱讀 921評(píng)論 0 2
  • ios13 UISegmentedControl 的 setTintColor 屬性失效锅纺, 新增了一個(gè)setSe...
    海利昂閱讀 9,187評(píng)論 3 5
  • iOS13適配 1.私有KVC 在Xcode10上編譯不會(huì)有問(wèn)題掷空,但是在Xcode11上編譯的會(huì)崩潰。并且- (v...
    輕重緩急閱讀 578評(píng)論 0 1
  • 1. 暗黑模式 iOS13使用暗黑模式時(shí)囤锉,UIView默認(rèn)背景色會(huì)變成暗黑色坦弟。適配暗黑模式的工作量較大,改為強(qiáng)制使...
    大斌小姜閱讀 6,126評(píng)論 0 3