iOS各版本差異匯總(從8.0開始且不包括UI篇)

一.前言介紹

? ? ? ?此文檔描述了從iOS8.0到目前的iOS13版本更新需要兼容的地方--- 僅供iOS開發(fā)人員參考

.iOS 8.0

1.定位功能使用改變

// 判斷定位操作是否被允許if([CLLocationManager locationServicesEnabled]) { ? ?locationManager = [[CLLocationManager alloc] init]; ? ?locationManager.delegate = self; ? ?[locationManager startUpdatingLocation];}else?{ ? ?//提示用戶無法進行定位操作}

如果在iOS8下用這樣的方式,你會發(fā)現(xiàn)無法定位,那是因為iOS8下添加了新的方法

?/表示使用應用程序期間 ?開啟定位 ?

- (void)requestWhenInUseAuthorization ?

//表示始終 開啟定位 ?

- (void)requestAlwaysAuthorization

兩者區(qū)別在于,iOS7 開始,有更強大的后臺運行功能,如果 用 requestAlwaysAuthorization 方法,則表示后臺運行時也會用到定位

iOS8 下使用系統(tǒng)定位如下:

/ 判斷定位操作是否被允許 ?

?if([CLLocationManager locationServicesEnabled]) { ?

? ? ? ? locationManager = [[CLLocationManager alloc] init]; ?

? ? ? ? locationManager.delegate = self; ?

?//兼容iOS8定位 ?

? ? ? ? SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization"); ?

?if?([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&

? ? ? ? ? ? [locationManager respondsToSelector:requestSelector]) { ?

? ? ? ? ? ? [locationManager requestWhenInUseAuthorization]; ?

}?else?{

? ? ? ? ? ? [locationManager startUpdatingLocation]; ?

? ? ? ? } ?

?return?YES;

? ? }else?{

?//提示用戶無法進行定位操作 ?

? ? } ?

?return?NO;

除了這些,你還需要在 info.plist 里面添加新的鍵值,否則 也是無法定位的

2.UIActionSheet and UIAlertView 的升級

在iOS8里面,官方提供了新的類UIAlertController來替換UIActionSheet and UIAlertView。

UIAlertController* alert = [UIAlertController?alertControllerWithTitle:@"My Alert"??message:@"This is an alert."??preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction defaultAction = [UIAlertAction?actionWithTitle:@"OK"style:UIAlertActionStyleDefault?handler:^(UIAlertAction ?action) {}];

[self?presentViewController:alert?animated:YES?completion:nil];

3.解決跳轉(zhuǎn)到系統(tǒng)設置里自己App的頁面

在iOS5.0時時可以跳轉(zhuǎn)到系統(tǒng)的設置頁的。但是在5.1之后就不可以了。

剛才研究了下這個問題,發(fā)現(xiàn)只有iOS8可以跳轉(zhuǎn)到系統(tǒng)設置里自己App的頁面。

目前沒有找到iOS7怎么跳轉(zhuǎn)過去。如果你知道請一定要留言告知,Thanks!

下面說下iOS8是如何跳轉(zhuǎn)的,以下是代碼:

NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];

if?([[UIApplication sharedApplication] canOpenURL:url]) {

? ?[[UIApplication sharedApplication] openURL:url];

}

.iOS 9.0

1.?后臺定位類app適配點

在iOS8中,APP的定位服務apple就做了一些修改,需要用戶申請相應的權(quán)限,并在info.plist文件中添加對應的鍵值

在iOS9系統(tǒng)中,定位服務的做法基本沒有改變,對于前臺的定位沒有影響,但app中如果需要后臺定位,那么還需要多做一些操作,例如:

manager = [[CLLocationManager alloc]init];

?//申請后臺定位權(quán)限

? ? [manager requestAlwaysAuthorization];

? ? manager.delegate=self;

?//=======================================

?//下面這個是iOS9中新增的方法 開啟后臺定位

? ? manager.allowsBackgroundLocationUpdates = YES;

?//======================================

? ? [manager startUpdatingLocation];

通過上面簡單的配置直接運行的話,程序會崩潰掉,還需要在plist文件中做一些配置

2.?安裝不受信任的開發(fā)者應用

我們知道,在Xcode7后,開發(fā)者可以不用花99dollars去購買開發(fā)者賬號而可以在自己的iphone上進行測試。在安裝這些應用時,iOS9系統(tǒng)不再向以前那樣,再安裝時提示一個信任的按鈕。

3.?BitCode的配置

BitCode是app的一種中間形式,在iOS9系列專題的前幾篇,有對其的簡單介紹,舉個例子,我們可以在提交app時提交app的bitcode形式,如此一來,apple會對我們的app進行二次優(yōu)化,在用戶下載時根據(jù)所需再進行編譯打包。在Xocde7中,新建的項目是默認開啟BitCode的,如果我們用Xcode7編譯提交應用,這里有需要注意適配的地方。

如果要支持BitCode,需要保證所有的SDK都支持BitCode,如果要更新舊的SDK,只需要在Xcode7上開啟BitCode重新制作一遍即可。

如果不能使所有SDK都支持BitCode,可以在項目中關閉BitCode,在building Setting中搜索BitCode,將enable設置為NO。

4.?URL Scheme白名單

在iOS9中,apple引入了白名單這個概念,其好處是對app應用內(nèi)安全進行了加強。在iOS9的適配中,如果我們用到canOpenURL這樣的方法,則需要配置白名單。

首先,我們創(chuàng)建一個測試工程,什么都不用做,只需要添加一個URL Scheme

?|

在另一個工程中,我們寫如下代碼:

BOOL can= [[UIApplication sharedApplication]canOpenURL:[NSURL URLWithString:@"TEST://"]];

? ? NSLog(@"%d",can);

? ? [[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"TEST://"]];

5.?iOS9網(wǎng)絡適配_ATS:改用更安全的HTTPS

為了強制增強數(shù)據(jù)訪問安全, iOS9 默認會把 所有的http請求 所有從NSURLConnection 、 CFURL 、 NSURLSession發(fā)出的 HTTP 請求,都改為 HTTPS 請求:iOS9.x-SDK編譯時,默認會讓所有從NSURLConnection 、 CFURL 、 NSURLSession發(fā)出的 HTTP 請求統(tǒng)一采用TLS 1.2 協(xié)議。因為 AFNetworking 現(xiàn)在的版本底層使用了 NSURLConnection ,眾多App將被影響(基于iOS8.x-SDK的App不受影響)。服務器因此需要更新,以解析相關數(shù)據(jù)。如不更新,可通過在 Info.plist 中聲明,倒退回不安全的網(wǎng)絡請求。而這一做法,官方文檔稱為ATS,全稱為App Transport Security,是iOS9的一個新特性。

<key>NSAppTransportSecurity</key>

<dict>

<key>NSAllowsArbitraryLoads</key>

<true/>

</dict>

<key>NSAppTransportSecurity</key>

<dict>

?<key>NSExceptionDomains</key>

?<dict>

?<key>yourserver.com</key>

?<dict>

?<!--Include to allow subdomains-->

?<key>NSIncludesSubdomains</key>

?<true/>

?<!--Include to allow insecure HTTP requests-->

?<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>

?<true/>

?<!--Include to specify minimum TLS version-->

?<key>NSTemporaryExceptionMinimumTLSVersion</key>

?<string>TLSv1.1</string>

?</dict>

?</dict>

</dict>

.iOS 10.0

1.?Notification(通知)

所有相關通知被統(tǒng)一到了UserNotifications.framework框架中

增加了撤銷、更新、中途還可以修改通知的內(nèi)容

通知不在是簡單的文本了,可以加入視頻、圖片,自定義通知的展示等等。

iOS 10相對之前的通知來說更加好用易于管理,并且進行了大規(guī)模優(yōu)化,對于開發(fā)者來說是一件好事

iOS 10開始對于權(quán)限問題進行了優(yōu)化,申請權(quán)限就比較簡單了(本地與遠程通知集成在一個方法中)。

2.?ATS的問題

iOS 9中默認非HTTS的網(wǎng)絡是被禁止的,當然我們也可以把NSAllowsArbitraryLoads設置為YES禁用ATS。不過iOS 10從2017年1月1日起蘋果不允許我們通過這個方法跳過ATS,也就是說強制我們用HTTPS,如果不這樣的話提交App可能會被拒絕。但是我們可以通過NSExceptionDomains來針對特定的域名開放HTTP可以容易通過審核。

3.?iOS 10 隱私權(quán)限設置

iOS 10 開始對隱私權(quán)限更加嚴格,如果你不設置就會直接崩潰,現(xiàn)在很多遇到崩潰問題了,一般解決辦法都是在info.plist文件添加對應的Key-Value就可以了。

?|

4.?iOS 10 UICollectionView 性能優(yōu)化

隨著開發(fā)者對UICollectionView的信賴,項目中用的地方也比較多,但是還是存在一些問題,比如有時會卡頓、加載慢等。所以iOS 10 對UICollectionView進一步的優(yōu)化。

UICollectionView cell pre-fetching預加載機制

UICollectionView and UITableView prefetchDataSource 新增的API

針對self-sizing cells 的改進

5.?UITextContentType

在iOS 10 UITextField添加了textContentType枚舉,指示文本輸入?yún)^(qū)域所期望的語義意義。

使用此屬性可以給鍵盤和系統(tǒng)信息,關于用戶輸入的內(nèi)容的預期的語義意義。例如,您可以指定一個文本字段,用戶填寫收到一封電子郵件確認uitextcontenttypeemailaddress。當您提供有關您期望用戶在文本輸入?yún)^(qū)域中輸入的內(nèi)容的信息時,系統(tǒng)可以在某些情況下自動選擇適當?shù)逆I盤,并提高鍵盤修正和主動與其他文本輸入機會的整合。

6.?字體隨著手機系統(tǒng)字體而改變

當我們手機系統(tǒng)字體改變了之后,那我們App的label也會跟著一起變化,這需要我們寫很多代碼來進一步處理才能實現(xiàn),但是iOS 10 提供了這樣的屬性adjustsFontForContentSizeCategory來設置。因為沒有真機,具體實際操作還沒去實現(xiàn),如果理解錯誤幫忙指正。

UILabel *myLabel = [UILabel?new];?/*

? ? UIFont 的preferredFontForTextStyle: 意思是指定一個樣式,并讓字體大小符合用戶設定的字體大小。

? ?*/

myLabel.font =[UIFont preferredFontForTextStyle: UIFontTextStyleHeadline];?/*

?Indicates whether the corresponding element should automatically update its font when the device’s UIContentSizeCategory is changed.

?For this property to take effect, the element’s font must be a font vended using +preferredFontForTextStyle: or +preferredFontForTextStyle:compatibleWithTraitCollection: with a valid UIFontTextStyle.

?*/

? ? ?//是否更新字體的變化

? ? myLabel.adjustsFontForContentSizeCategory = YES;

7.?系統(tǒng)版本判斷方法失效

我們之前的系統(tǒng)版本方法如下

當系統(tǒng)版本到iOS10.0的時候 9.0和10.0比較的話是降序而不是升序,這樣會導致iOS10.0是最早的版本,這樣后面要走的iOS10的方法可能都不會走而出現(xiàn)問題

#define?IOS9_OR_LATER ([[[UIDevice currentDevice] systemVersion] compare:@"9.0"] != NSOrderedAscending)

#define?IOS8_OR_LATER ([[[UIDevice currentDevice] systemVersion] compare:@"8.0"] != NSOrderedAscending)

#define?IOS7_OR_LATER ([[[UIDevice currentDevice] systemVersion] compare:@"7.0"] != NSOrderedAscending)

#define?IOS6_OR_LATER ([[[UIDevice currentDevice] systemVersion] compare:@"6.0"] != NSOrderedAscending)

下面這樣也不行它會永遠返回NO,substringToIndex:1在iOS 10 會被檢測成 iOS 1了,

#define isiOS10 ([[[[UIDevice currentDevice] systemVersion] substringToIndex:1] intValue]>=10)

正確的打開方式應該是:

#define?IOS10_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0)

#define?IOS9_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0)

#define?IOS8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)

#define?IOS7_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

#define?IOS6_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0)

8.?Xcode8 debug輸出不相關信息

升級到Xcode8時,我們在debug的時候控制臺輸出了很長很長的信息,看著比較煩,怎么屏蔽呢?

需要edit Scheme添加一個鍵值對就ok了。

?|

?|

添加 key:?OS_ACTIVITY_MODE??value:?disable?

9.App跳轉(zhuǎn)設置

? openUrl:

? openURL: options: completionHandler:

? prefs:root=某項服務

若要跳轉(zhuǎn)系統(tǒng)設置,需先再URL type中添加一個prefs值,如下圖:

?|

10.?判斷版本方法

【【UIDevice currentDevice】systemVersion】

11.推送xcode適配開關

在targets的Capabiliies內(nèi)Push Notifications選項開關打開

?|

然后Background Modes打開如下幾個選項

?|

General內(nèi)導入UserNotifications.framework

?|

12.Xib文件

1) 使用Xcode8 打開xib文件是會出現(xiàn)“choose an initial device view”的提示,直接選擇藍色的 choose Device 就可以了。

2) 如果布局混亂,在xib的右下角更新一下,即 Update Frame。

13.代碼及API

1) UIView的代理方法可能會出現(xiàn)報錯,刪除NSError前面的 nullable就行了。

2) UIStatusBar的方法過期了,如果項目中設置了statusBar,那就像下面這樣寫:

- (UIStatusBarStyle)preferredStatusBarStyle {?

?return?UIStatusBarStyleDefault;

}

.iOS 11.0

1.XCode9運行訪問系統(tǒng)相冊崩潰問題

現(xiàn)象:如圖保存圖片功能,在XCode9下運行會崩潰

原因:info.plist新增了權(quán)限配置

解決:info.plist新增一條權(quán)限:Privacy - Photo Library Additions Usage Description

2.無法獲取定位信息,第一次打開app也無法彈出定位權(quán)限提示框

iOS11 定位相關的權(quán)限做了更改,在iOS11上使用了新的定位權(quán)限key

解決方案:

如果原來申請的權(quán)限是始終允許NSLocationAlwaysUsageDescription,那么需要在保留原來的key的基礎上增加NSLocationWhenInUseUsageDescription和NSLocationAlwaysAndWhenInUsageDescription。

3.無線真機測試

這應該也是?xcode 9?的一個亮點吧,但是速度真的不是很干恭維的。注意手機和電腦必須在同一個局域網(wǎng)內(nèi)

首先使用手機連接xcode之后,打開?window->Devices and Simulator->勾選Show as run destination和Connect via network?,這樣就可以無線測試了,以后媽媽再也不用擔心忘記帶線了

?|

?|

iOS11UI方面的適配較多,如啟動圖、tabbar、劉海兒、導航欄、啟動圖等適配這些UI方面的適配就沒有整理了。。。。。。

.iOS 12.0

1.代碼中判斷是否是iPhone X方法

之前很多人判斷手機是否是iPhone X的方法是根據(jù)手機尺寸來的.因為需要對劉海做特殊處理.現(xiàn)在這種方法可能不行了.

可以根據(jù)其他的方法,比如StatusBar或者底部安全距離來判斷.

#define?rmStatusBarH ([UIApplication sharedApplication].statusBarFrame.size.height)//(44/20)

#define?KIsiPhoneX ((rmStatusBarH == 44.0) ? YES : NO)

也可以:

#define isIPhoneXSeries ? ? ([UIScreen instancesRespondToSelector:@selector(currentMode)] ?\

(\

CGSizeEqualToSize(CGSizeMake(375,?812),[UIScreen mainScreen].bounds.size)\

?||\

CGSizeEqualToSize(CGSizeMake(414,?896),[UIScreen mainScreen].bounds.size)\

)\

:\

NO)

2.升級Xcode10后項目報錯

項目中如果使用Cocoapods引用了第三方的庫,有可能會升級之后導致編譯失敗.

由于我項目中沒有使用cocoapods,所以沒有遇到,網(wǎng)上查了一下資料,大概是因為:

iOS 12移除了libstdc++, 用libc++替代:

多個 info.plist 會引起崩潰.

可以將多余的info.plist刪除

建議方案:

Xcode->File->Project Settings-> Build System -> Legacy Build System.

3.Multiple commands produce 'xxx/Info.plist'

升級?Xcode 10?之后,編譯之前的項目,發(fā)生編譯錯誤:?Multiple commands produce 'xxx/Info.plist'?,項目中存在重復命名的info.plist文件。

解決方案:

(I)標準方案:刪除所有重復命名的文件。

(II)臨時方案:

?xcworkspace?項目:Xcode菜單欄?File??->??Workspace Settings??->??Build System??->??Legacy Build System?;

?xcodeprj?項目:Xcode菜單欄?File??->??Project Settings??->??Build System??->??Legacy Build System?。

4.?iOS 12?系統(tǒng)?WiFi?獲取?SSID?(wifi名稱)和?BSSID?(mac地址)失敗

在?iOS 12?系統(tǒng)之后,蘋果提升了獲取?WiFi?名稱和?mac?地址的權(quán)限控制,要獲取這些信息,需要手動為應用打開獲取WiFi信息的權(quán)限。

解決方案:

在開發(fā)者賬號中,勾選項目的?App ID?的?Access WiFi Infomation?選項;

在Xcode的?Capabilities?中,勾選項目的?Access WiFi Infomation?選項。

5.?Xcode 10?中?#import?的時候閃退或?qū)腩^文件不提示

在?Xcode 10?中出現(xiàn)輸入?#import?引入文件/類庫頭文件的時候?Xcode?閃退。或者輸入?#import?導入頭文件時不提示。

解決方案:

?xcworkspace?項目:Xcode菜單欄?File??->??Workspace Settings??->??Build System??->??Legacy Build System?;

?xcodeprj?項目:Xcode菜單欄?File??->??Project Settings??->??Build System??->??Legacy Build System?。

6.?webView?播放視頻返回后狀態(tài)欄消失

視頻播放完成主?window?成為?KeyWindow?的時候仍隱藏著?UIStatusBar?。

解決方案:

- (void)videoPlayerFinishedToShowStatusBar

{

?if?(@available(iOS 12.0, *)) {

? ? ? ? [[NSNotificationCenter defaultCenter] addObserverForName:UIWindowDidBecomeKeyNotification

?object:self.window

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?queue:[NSOperationQueue mainQueue]

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? usingBlock:^(NSNotification * _Nonnull note) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [[UIApplication sharedApplication] setStatusBarHidden:NO

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? withAnimation:UIStatusBarAnimationNone];

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }];

? ? }

}

7.Xcode 10 ?imageNamed: 不能正常加載Assets里面的圖片

imageNamed:加載Assets中的圖片出來是nil,將圖片放到bundle中即可。

.iOS 13.0

1.私有KVC

iOS不允許?valueForKey?、?setValue: forKey?獲取和設置私有屬性,需要使用其它方式修改

如:

[textField setValue:[UIColor red] forKeyPath:@"_placeholderLabel.textColor"];

//替換為

textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"輸入"attributes:@{NSForegroundColorAttributeName: [UIColor red]}];

2.黑線處理crash

之前為了處理搜索框的黑線問題會遍歷后刪除?UISearchBarBackground?,在iOS13會導致UI渲染失敗crash;解決辦法是設置?UISearchBarBackground?的layer.contents為nil

public?func?clearBlackLine()?{

?for?view in self.subviews.last!.subviews {

?if?view.isKind(of: NSClassFromString("UISearchBarBackground")!) {

? ? ? ? ? ? ? ? view.backgroundColor = UIColor.white

view.layer.contents =?nil

?break

? ? ? ? ? ? }

? ? ? ? }

? ? }

3.模態(tài)跳轉(zhuǎn)(modal present)

iOS13模態(tài)跳轉(zhuǎn)出來的界面,不再像之前版本是全屏的了

如果將此屬性設置為?UIModalPresentationAutomatic?,則讀取該屬性將始終返回具體的呈現(xiàn)樣式。 默認情況下,?UIViewController?將?UIModalPresentationAutomatic?解析為?UIModalPresentationPageSheet?,但是系統(tǒng)提供的子類可以將?UIModalPresentationAutomatic?解析為其他具體的呈現(xiàn)樣式。 保留?UIModalPresentationAutomatic?的分辨率供系統(tǒng)提供的視圖控制器使用。從iOS 13.0開始,在iOS上默認為?UIModalPresentationAutomatic?,在以前的版本上默認為?UIModalPresentationFullScreen?。 在所有其他平臺上,默認為?UIModalPresentationFullScreen?。

?UIModalPresentationPageSheet?就是下面的樣子

?|

知道了原因,我們做適配也簡單了,就是設置下屬性的事:

let second = SecondViewController()

second.modalPresentationStyle = .fullScreen

present(second, animated:?true, completion:?nil)

4.暗黑模式

iOS13使用暗黑模式時,UIView默認背景色會變成暗黑色。適配暗黑模式的工作量較大,改為強制使用正常模式。

處理方案:在plist文件中增加配置項UIUserInterfaceStyle,值為Light。

5.藍牙權(quán)限更新

上傳App Store時,如果引用了CoreBluetooth.framework,則需要添加描述配置?NSBluetoothAlwaysUsageDescription?,否則無法提交。舊版本的個推SDK引入時依賴CoreBluetooth,后續(xù)版本已修改不再依賴CoreBluetooth。

處理方案:檢查其他第三方庫并未依賴CoreBluetooth.framework,刪除對該庫的引用。

6.廢棄UIWebview改為WKWebView

暫時沒有強制修改,但是已經(jīng)發(fā)郵件提示,需要做一下修改,否則可能無法上架哈

7.KVC限制

在iOS13上通過KVC來修改系統(tǒng)API私有屬性時會報錯

*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Access to xxx's _xxx ivar is prohibited. This is an application bug'

處理方案:

1、全局搜索KVC的使用方法,未發(fā)現(xiàn)使用KVC方式修改私有屬性的代碼

2、平時開發(fā)時注意KVC的使用

8. 第三方登錄支持蘋果登錄(Sign In with Apple)

蘋果更新了審核指南,要求所有專門使用第三方登錄的App,2020 年 4 月之前,都必須接入 Sign in with Apple。符合以下條件的App,可以不接入:

使用自建賬戶和登錄系統(tǒng);

要求用戶使用現(xiàn)有的教育或企業(yè)賬戶登錄的教育、企業(yè)或商業(yè)類應用;

使用政府或行業(yè)支持的公民身份識別系統(tǒng)或電子 ID 來驗證用戶;

應用特定于第三方服務,用戶需要使用郵箱、社交媒體或其它第三方賬戶才能訪問其內(nèi)容的應用;

9.使用MJExtension 中處理NSNull的不同

這個直接會導致Crash的在將服務端數(shù)據(jù)字典轉(zhuǎn)換為模型時,如果遇到服務端給的數(shù)據(jù)為NSNull時,

mj_JSONObject,其中 class_copyPropertyList方法得到的屬性里,多了一種EFSQLBinding類型的東西,而且屬性數(shù)量也不準確,

那就沒辦法了,

我只能改寫這個方法了,這個組件沒有更新的情況下,寫了一個方法swizzling掉把當遇到 NSNull時,直接轉(zhuǎn)為nil了。

10.WKWebView 中測量頁面內(nèi)容高度的方式變更

iOS 13以前

document.body.scrollHeight

iOS 13中

document.documentElement.scrollHeight

兩者相差55 應該是瀏覽器定義高度變了

11. 友盟消息推送,獲取deviceToken適配

- (void)application:(UIApplication *)applicationdidRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{if(![deviceToken isKindOfClass:[NSData class]])return; ? ? ?const?unsigned?*tokenBytes = (constunsigned?*)[deviceToken bytes]; ? ? ?NSString *hexToken = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x",ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),ntohl(tokenBytes[6]),ntohl(tokenBytes[7])]; ? ? ?pushDeviceToken = hexToken; ? ? ?NSLog(@"deviceToken:%@",hexToken);}

12.獲取Wi-Fi名

iOS12之前

id info =?nil;

? ? NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();

?for?(NSString *ifnam?in?ifs) {

? ? ? ? info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);

? ? ? ? NSString *str = info[@"SSID"];//name

? ? }

iOS 12之后以上方法獲取不到,需要在Xcode中TARGET-->Capabilities打開Access WiFi Information選項

?|

iOS 13之后以上方法獲取Wi-Fi名返回的都是固定值"WLAN",這里可能是因為蘋果保護用戶隱私而產(chǎn)生的問題,因為通過wifi信息可以定位到用戶地理位置。所以iOS13以后如果想要繼續(xù)獲取WiFi名稱,需要在調(diào)用接口前判斷用戶是否同意App使用地理位置信息??梢栽诔绦蛞粏訒r請求用戶權(quán)限,調(diào)用的方法如下:

#import <CoreLocation/CoreLocation.h>

@property (strong, nonatomic) CLLocationManager *locationManager;

NSString* phoneVersion = [[UIDevice currentDevice] systemVersion];

CGFloat version = [phoneVersion floatValue];

// 如果是iOS13 未開啟地理位置權(quán)限 需要提示一下

if?([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined && version >=?13) {

?self.locationManager = [[CLLocationManager alloc] init];

? ? [self.locationManager requestWhenInUseAuthorization];

}

如果用戶拒絕了授權(quán),在需要獲取Wi-Fi名的界面加上提示:

? ? NSString* phoneVersion = [[UIDevice currentDevice] systemVersion];

? ? CGFloat version = [phoneVersion floatValue];

? ? //如果開啟地理位置權(quán)限未開啟 需要提示一下

?if?(([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined?||[CLLocationManager authorizationStatus] == kCLAuthorizationStatusRestricted?||[CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied ?)&& version >=?13) {

[PracticalTools?showAlertViewWithTitle:@"提示"?message:@"您的位置權(quán)限尚未授權(quán),將無法獲取當前Wi-Fi進行配置網(wǎng)絡,請前往“設置”-“****App”-“位置”進行授權(quán)!"?doneText:@"確定"?cancelText:nildoneHandle:nil?cancelHandle:nil?vc:self];

? ? }

13.iOS13 正確的獲得Devicetoken

#include?<arpa/inet.h>

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

{

?if?(![deviceToken isKindOfClass:[NSData class]])?return;

?const?unsigned?*tokenBytes = (const?unsigned?*)[deviceToken bytes];

? ? NSString *hexToken = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x",

? ? ? ? ? ? ? ? ? ? ? ? ? ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),

? ? ? ? ? ? ? ? ? ? ? ? ? ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),

? ? ? ? ? ? ? ? ? ? ? ? ? ntohl(tokenBytes[6]), ntohl(tokenBytes[7])];

? ? NSLog(@"deviceToken:%@",hexToken);

}

14.Xcode 11 創(chuàng)建的工程在低版本設備上運行黑屏

使用 Xcode 11 創(chuàng)建的工程,運行設備選擇 iOS 13.0 以下的設備,運行應用時會出現(xiàn)黑屏。這是因為 Xcode 11 默認是會創(chuàng)建通過 UIScene 管理多個 UIWindow 的應用,工程中除了 AppDelegate 外會多一個 SceneDelegate.

?|

這是為了 iPadOS 的多進程準備的,也就是說 UIWindow 不再是 UIApplication 中管理。但是舊版本根本沒有 UIScene,因此解決方案就是在 AppDelegate 的頭文件加上:

@property (strong, nonatomic) UIWindow *window;

15.NSAttributedString優(yōu)化

對于UILabel、UITextField、UITextView,在設置NSAttributedString時也要考慮適配Dark Mode,否則在切換模式時會與背景色融合,造成不好的體驗

不建議的做法

NSDictionary *dic = @{NSFontAttributeName:[UIFont systemFontOfSize:16]};

NSAttributedString *str = [[NSAttributedString alloc] initWithString:@"富文本文案"attributes:dic];

推薦的做法

// 添加一個NSForegroundColorAttributeName屬性

NSDictionary *dic = @{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName:[UIColor labelColor]};

NSAttributedString *str = [[NSAttributedString alloc] initWithString:@"富文本文案"attributes:dic];

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容