@(IOS各個版本適配)javascript
[TOC]css
Xcode10是默認選中的最新的New Build System(Default)
,在這個編譯系統的環境下,不容許多個info.plistjava
把build system
切換到 Legacy Build System
,換言之就是切換成老的編譯系統,就OK了。 Xcode->File->Project Settings-> Build System -> Legacy Build System.
ios
刪除其餘info.plist文件。c++
Xcode10中libstdc++相關的3個庫(libstdc++、libstdc++.六、libstdc++6.0.9)應該都是被完全廢棄了,若是你使用的三方庫中有依賴,請儘快和提供方溝通,告知他們遷移吧。若是本身開發使用,也儘快考慮遷移的事宜吧。git
if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {
}
複製代碼
self.traitCollection.forceTouchCapability == .availible
複製代碼
iOS11爲
UIViewController
和UIView
增長了兩個新的屬性safeAreaInsets
和safeAreaLayoutGuide
github
safeAreaInsets
適用於手動計算.safeAreaLayoutGuide
適用於自動佈局.UIViewController中新增:
- (void)viewSafeAreaInsetsDidChange;
UIView中新增:
- (void)viewSafeAreaInsetsDidChange;
複製代碼
在
Storyboard
使用Safe Area
最低只支持iOS9
,iOS8
的用戶就要放棄了json
當
UIViewController
調用- (void)viewDidLoad
時它的全部子視圖的safeAreaInsets
屬性都等於UIEdgeInsetsZero
。swift
viewSafeAreaInsetsDidChange
的調用時機以下:segmentfault
viewDidLoad
viewWillAppear
viewSafeAreaInsetsDidChange
viewWillLayoutSubviews
viewDidAppear
只有在調用
viewSafeAreaInsetsDidChange
後,才能得到view
以及viewController
的SafeArea(UIEdgeInsets)
。所以在viewDidload
中根據SafeArea
設置界面會有問題。
safeAreaInsets
= (top
= 44, left
= 0, bottom
= 34, right
= 0)safeAreaInsets
= (top
= 0, left
= 44, bottom
= 21, right
= 44)#import "Adaptive11VC.h"
static inline UIEdgeInsets sgm_safeAreaInset(UIView *view) {
if (@available(iOS 11.0, *)) {
return view.safeAreaInsets;
}
return UIEdgeInsetsZero;
}
@interface Adaptive11VC ()
@end
@implementation Adaptive11VC
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)testSafeArea {
UIEdgeInsets safeAreaInsets = sgm_safeAreaInset(self.view);
NSLog(@"safeAreaInsets = %@", NSStringFromUIEdgeInsets(safeAreaInsets));
}
- (void)viewSafeAreaInsetsDidChange {
[super viewSafeAreaInsetsDidChange];
[self testSafeArea];
}
@end
複製代碼
iOS 11廢棄了UIViewController
的automaticallyAdjustsScrollViewInsets
屬性,新增了contentInsetAdjustmentBehavior
屬性,因此當超出安全區域時系統自動調整了SafeAreaInsets
,進而影響了adjustedContentInset
,在iOS11中決定tableView
內容與邊緣距離的是adjustedContentInset
,因此須要設置UIScrollView
的contentInsetAdjustmentBehavior
屬性。
// 方式一:(不推薦)修改額外的安全區域
if (@available(iOS 11.0, *)) {
self.additionalSafeAreaInsets = UIEdgeInsetsMake(-44, 0, 0, 0);
}
else {
// Fallback on earlier versions
}
// 方式二:(推薦)設置爲不自動調整
if (@available(iOS 11.0, *)) {
// 做用於指定的UIScrollView
self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
// 做用與全部的UIScrollView
UIScrollView.appearance.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
else {
self.automaticallyAdjustsScrollViewInsets = NO;
}
複製代碼
iOS11開始UITableView
開啓了自動估算行高,estimatedRowHeight
estimatedSectionHeaderHeight
estimatedSectionFooterHeight
三個高度估算屬性由默認的0變成了UITableViewAutomaticDimension
,若是不實現-tableView: viewForFooterInSection:
和 -tableView: viewForHeaderInSection:
,那麼estimatedRowHeight
estimatedSectionHeaderHeight
estimatedSectionFooterHeight
三個高度估算屬性由默認的0變成了UITableViewAutomaticDimension
,致使高度計算不對,會產生空白。解決方法是實現對應方法或吧這三個屬性設爲0。
本地認證框架提供了從具備指定安全策略(密碼或生物學特徵)的用戶請求身份驗證的功能。例如,要求用戶僅使用Face ID或Touch ID進行身份驗證,可以使用如下代碼:
#import <LocalAuthentication/LocalAuthentication.h>
/**
檢測TouchID是否可用
*/
- (void)checkBiometrics {
LAContext *context = [[LAContext alloc] init];
BOOL success = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
error:nil];
if ( success ) {
NSLog(@"can use");
}
else {
NSLog(@"can`t use ");
}
}
/**
在驗證TouchID可用的狀況下使用
*/
- (void)excuteBiometrics {
LAContext *context = [[LAContext alloc] init];
context.localizedFallbackTitle = @"自定義標題";
[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:@"爲何使用TouchID寫這裏"
reply:^(BOOL success, NSError * _Nullable error) {
if ( success ) {
// 指紋驗證成功
}
else {
switch (error.code) {
case LAErrorUserFallback:{
NSLog(@"用戶選擇輸入密碼");
break;
}
case LAErrorAuthenticationFailed:{
NSLog(@"驗證失敗");
break;
}
case LAErrorUserCancel:{
NSLog(@"用戶取消");
break;
}
case LAErrorSystemCancel:{
NSLog(@"系統取消");
break;
}
// 如下三種狀況若是提早檢測TouchID是否可用就不會出現
case LAErrorPasscodeNotSet:{
break;
}
case LAErrorTouchIDNotAvailable:{
break;
}
case LAErrorTouchIDNotEnrolled:{
break;
}
default:
break;
}
}
}];
}
複製代碼
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "2436h",
"filename" : "1125_2436.png",
"minimum-system-version" : "11.0",
"orientation" : "portrait",
"scale" : "3x"
}
複製代碼
在 iOS 11 中必須支持
When In Use
受權模式(NSLocationWhenInUseUsageDescription
),在 iOS 11 中,爲了不開發者只提供請求 Always 受權模式這種狀況,加入此限制,若是不提供When In Use
受權模式,那麼Always
相關受權模式也沒法正常使用。
若是要支持老版本,即 iOS 11 如下系統版本,那麼建議在 info.plist 中配置全部的 Key(即便 NSLocationAlwaysUsageDescription
在 iOS 11及以上版本再也不使用):
NSLocationWhenInUseUsageDescription
NSLocationAlwaysAndWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
NSLocationAlwaysAndWhenInUseUsageDescription // 爲 iOS 11 中新引入的一個 Key。
複製代碼
Xcode8取消了三方插件(不少優秀的插件,原本能夠顯著提升效率)的功能,使用Extension代替 Xcode 8 Extension 推薦
爲了方便用戶來管理,提供Automatically manage signing
。須要輸入開發者帳號!若是沒有帳號也不要緊,在下面也能夠選擇Debug
、Realease
、inHouse
模式下對應的證書也能夠!
iOS10,蘋果增強了對隱私數據的保護,要對隱私數據權限作一個適配,iOS10調用相機,訪問通信錄,訪問相冊等都要在info.plist中加入權限訪問描述,否則以前大家的項目涉及到這些權限的地方就會直接crash掉。
解決辦法: 只須要在info.plist
添加NSContactsUsageDescription
的key
, value
本身隨意填寫就能夠,這裏列舉出對應的key(Source Code模式下):
<key>NSPhotoLibraryUsageDescription</key><string>App須要您的贊成,才能訪問相冊</string>
<key>NSCameraUsageDescription</key><string>App須要您的贊成,才能訪問相機</string>
<key>NSMicrophoneUsageDescription</key><string>App須要您的贊成,才能訪問麥克風</string>
<key>NSLocationUsageDescription</key><string>App須要您的贊成,才能訪問位置</string>
<key>NSLocationWhenInUseUsageDescription</key><string>App須要您的贊成,才能在使用期間訪問位置</string>
<key>NSLocationAlwaysUsageDescription</key><string>App須要您的贊成,才能始終訪問位置</string>
<key>NSCalendarsUsageDescription</key><string>App須要您的贊成,才能訪問日曆</string>
<key>NSRemindersUsageDescription</key><string>App須要您的贊成,才能訪問提醒事項</string>
<key>NSMotionUsageDescription</key><string>App須要您的贊成,才能訪問運動與健身</string>
<key>NSHealthUpdateUsageDescription</key><string>App須要您的贊成,才能訪問健康更新 </string>
<key>NSHealthShareUsageDescription</key><string>App須要您的贊成,才能訪問健康分享</string>
<key>NSBluetoothPeripheralUsageDescription</key><string>App須要您的贊成,才能訪問藍牙</string>
<key>NSAppleMusicUsageDescription</key><string>App須要您的贊成,才能訪問媒體資料庫</string>
複製代碼
隱私數據 | 對應key值 |
---|---|
相冊 | NSPhotoLibraryUsageDescription |
相機 | NSCameraUsageDescription |
麥克風 | NSMicrophoneUsageDescription |
位置 | NSLocationUsageDescription |
在使用期間訪問位置 | NSLocationWhenInUseUsageDescription |
始終訪問位置 | NSLocationAlwaysUsageDescription |
日曆 | NSCalendarsUsageDescription |
提醒事項 | NSRemindersUsageDescription |
運動與健身 | NSMotionUsageDescription |
健康更新 | NSHealthUpdateUsageDescription |
健康分享 | NSHealthShareUsageDescription |
藍牙 | NSBluetoothPeripheralUsageDescription |
媒體資料庫 | NSAppleMusicUsageDescription |
iOS 10 幹掉了全部系統設置的 URL Scheme,這意味着你不再可能直接跳轉到系統設置頁面(好比 WiFi、蜂窩數據、定位等)。
方式一:prefs:root=某項服務 適用於 小於 iOS10的系統; NSURL *url = [NSURL URLWithString:@"prefs:root=WIFI"];
方式二:prefs:root=bundleID 適用於 大於等於iOS8系統,小於iOS10的系統 NSURL *url = [NSURL URLWithString:@"prefs:root=bundleID"];
方式三:UIApplicationOpenSettingsURLString 適用於 大於等於iOS8的系統 NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
// iOS系統版本 >= 10.0
{
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
if ([[UIApplication sharedApplication] canOpenURL:url]) {
[[UIApplication sharedApplication] openURL:url];
}
}
return;
// iOS系統版本 >= 10.0
// But! 不建議這樣作哦,官方文檔中說過:
// `URL is now considered a private API and use will result in app rejection`.
// 雖然是有可能躲過蘋果的檢測,可是蘋果若是發現你這樣用了,app上架是有被拒的風險的.
{
NSURL *url = [NSURL URLWithString:@"APP-Prefs:root=WIFI"];
if ([[UIApplication sharedApplication] canOpenURL:url]) {
if (@available(iOS 10.0, *)) {
[[UIApplication sharedApplication] openURL:url
options:@{}
completionHandler:nil];
} else {
// Fallback on earlier versions
}
}
}
// iOS系統版本 < 10.0
{
NSURL *url = [NSURL URLWithString:@"prefs:root=WIFI"];
if ([[UIApplication sharedApplication] canOpenURL:url]) {
[[UIApplication sharedApplication] openURL:url];
}
}
複製代碼
prefs:root=bundleID ,bundleID
是你第三方應用工程的惟一ID蘋果的默認字體會隨着iOS系統版本的不一樣而不一樣,iOS10中字體變大了。致使了原來的顯示有問題,會形成...的出現。暫時沒有好的解決辦法,須要本身在一個個適配一下!
在iOS 10 以前,cell只能從重用隊列裏面取出,再走一遍生命週期,並調用cellForItemAtIndexPath建立或者生成一個cell.
在iOS 10 中,系統會cell保存一段時間,也就是說當用戶把cell滑出屏幕之後,若是又滑動回來,cell不用再走一遍生命週期了,只須要調用willDisplayCell方法就能夠從新出如今屏幕中了.
iOS 10 中,系統是一個一個加載cell的,二之前是一行一行加載的,這樣就能夠提高不少性能;
iOS 10 新增長的Pre-Fetching預加載
在iOS 10 中, UIRefreshControl能夠直接在UICollectionView和UITableView中使用,而且脫離了UITableViewController.如今RefreshControl是UIScrollView的一個屬性.
iOS 10全部相關通知被統一到了UserNotifications.framework框架中。增長了撤銷、更新、中途還能夠修改通知的內容。通知不在是簡單的文本了,能夠加入視頻、圖片,自定義通知的展現等等。
iOS 10相對以前的通知來講更加好用易於管理,而且進行了大規模優化,對於開發者來講是一件好事。
iOS 10開始對於權限問題進行了優化,申請權限就比較簡單了(本地與遠程通知集成在一個方法中)。
Xcode7 默認啓用 Bitcode,可是若是咱們用到的第三方庫編譯時還沒啓用 Bitcode,主工程就會編譯不過。Bitcode 是蘋果 App Thinning 的機制之一,能夠減小安裝包的大小。App store 會將這個 Bitcode 編譯爲可執行的64位或32位程序。
解決辦法一: 最簡單的解決辦法是先把 Bitcode 關掉:把 Build settings - Build Options - Enable Bitcode 改成 NO。
![]()
解決辦法二: 移除不支持BitCode的平臺SDK,或者尋找支持BitCode的替代品,或者聯繫SDK方支持BitCode。
iOS9 默認不支持 HTTP 請求,須要改用更安全的 HTTPS(默認用 TLS 1.2)。蘋果還提供了配置,使得全部安全性更低的網絡請求也能使用,解決方案就是在 info.plist 裏面增長如下配置:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
複製代碼
若是複雜一些,還能夠指定白名單域名,聲明所支持 TLS 的最低版本。另外須要注意的是,即便寫了上述配置,在 HTTPS 頁面中,HTTP 的 javascript 或 css 不會被加載,由於蘋果認爲這下降了頁面的安全性。
canOpenUrl 能夠用來判斷用戶是否安裝了某個 APP。也許是出於用戶隱私的考慮,iOS9 上對 canOpenUrl 作了限制,最多隻能對 50 個 scheme 作判斷。若是是用 Xcode7 編譯,須要在 plist 裏面聲明這些 scheme,沒有聲明的會直接返回 NO:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>weixin</string>
<string>wechat</string>
</array>
複製代碼
iOS9中廢棄的方法
// 修改狀態欄的樣式爲白色
// 'setStatusBarStyle(_:animated:)' was deprecated in iOS 9.0: Use -[UIViewController preferredStatusBarStyle]
UIApplication.shared.setStatusBarStyle(.lightContent, animated: true)
// 隱藏狀態欄
// 'setStatusBarHidden(_:with:)' was deprecated in iOS 9.0: Use -[UIViewController prefersStatusBarHidden]
UIApplication.shared.setStatusBarHidden(true, with: .fade)
複製代碼
用下面兩個方法替換
-[UIViewController preferredStatusBarstyle]
-[UIViewController preferredStatusBarHidden]
複製代碼