iOS十二、iOS十一、iOS十、iOS9常見適配

@(IOS各個版本適配)javascript

[TOC]css

1、iOS12(Xcode10)

1.一、升級Xcode10後項目報錯

不容許多個info.plist

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++

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

Xcode10中libstdc++相關的3個庫(libstdc++、libstdc++.六、libstdc++6.0.9)應該都是被完全廢棄了,若是你使用的三方庫中有依賴,請儘快和提供方溝通,告知他們遷移吧。若是本身開發使用,也儘快考慮遷移的事宜吧。git

1.二、iPhone XR不支持3D-Touch

OC檢測代碼
if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {

}
複製代碼
swift檢測代碼
self.traitCollection.forceTouchCapability == .availible
複製代碼

2、iOS11(Xcode9)

2.一、安全區域(SafeArea)

iOS11爲UIViewControllerUIView增長了兩個新的屬性safeAreaInsetssafeAreaLayoutGuidegithub

  • safeAreaInsets 適用於手動計算.
  • safeAreaLayoutGuide 適用於自動佈局.
UIViewController中新增:
- (void)viewSafeAreaInsetsDidChange;
UIView中新增:
- (void)viewSafeAreaInsetsDidChange;
複製代碼

Storyboard使用Safe Area最低只支持iOS9iOS8的用戶就要放棄了json

UIViewController調用- (void)viewDidLoad時它的全部子視圖的safeAreaInsets屬性都等於UIEdgeInsetsZeroswift

viewSafeAreaInsetsDidChange的調用時機以下:segmentfault

  • 一、viewDidLoad
  • 二、viewWillAppear
  • 三、viewSafeAreaInsetsDidChange
  • 四、viewWillLayoutSubviews
  • 五、viewDidAppear

只有在調用viewSafeAreaInsetsDidChange後,才能得到view以及viewControllerSafeArea(UIEdgeInsets)。所以在viewDidload中根據SafeArea設置界面會有問題。

iPhone X:有導航欄的時候能夠+44

豎屏 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
複製代碼

2.二、UIScrollView

iOS 11廢棄了UIViewControllerautomaticallyAdjustsScrollViewInsets屬性,新增了contentInsetAdjustmentBehavior屬性,因此當超出安全區域時系統自動調整了SafeAreaInsets,進而影響了adjustedContentInset,在iOS11中決定tableView內容與邊緣距離的是adjustedContentInset,因此須要設置UIScrollViewcontentInsetAdjustmentBehavior屬性。

// 方式一:(不推薦)修改額外的安全區域
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;
}
複製代碼

2.三、tableview問題

iOS11開始UITableView開啓了自動估算行高estimatedRowHeight estimatedSectionHeaderHeight estimatedSectionFooterHeight三個高度估算屬性由默認的0變成了UITableViewAutomaticDimension,若是不實現-tableView: viewForFooterInSection:-tableView: viewForHeaderInSection:,那麼estimatedRowHeight estimatedSectionHeaderHeight estimatedSectionFooterHeight三個高度估算屬性由默認的0變成了UITableViewAutomaticDimension,致使高度計算不對,會產生空白。解決方法是實現對應方法或吧這三個屬性設爲0。

2.四、LocalAuthentication 本地認證

本地認證框架提供了從具備指定安全策略(密碼或生物學特徵)的用戶請求身份驗證的功能。例如,要求用戶僅使用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;
            }
        }
    }];
}
複製代碼

2.五、啓動圖的適配

方法一:經過LaunchScreen.storyboard方式啓動

方法二:使用Assets中的LaunchImage

  • 給Brand Assets添加一張1125*2436大小的圖片
    • 打開Assets.xcassets文件夾,找到Brand Assets
    • 右鍵Show in Finder
    • 添加一張1125*2436大小的圖片
  • 修改Contents.json文件,添加以下內容
{
	"extent" : "full-screen",
	"idiom" : "iphone",
	"subtype" : "2436h",
	"filename" : "1125_2436.png",
	"minimum-system-version" : "11.0",
	"orientation" : "portrait",
	"scale" : "3x"
}
複製代碼

2.六、定位相關

在 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。
複製代碼

2.七、iOS11中 UIKit’s Bars 上的變化

3、iOS10(Xcode8)

3.一、(Why?Safe!)插件取消

Xcode8取消了三方插件(不少優秀的插件,原本能夠顯著提升效率)的功能,使用Extension代替 Xcode 8 Extension 推薦

3.二、證書問題

爲了方便用戶來管理,提供Automatically manage signing。須要輸入開發者帳號!若是沒有帳號也不要緊,在下面也能夠選擇DebugRealeaseinHouse模式下對應的證書也能夠!

3.三、隱私數據訪問問題

iOS10,蘋果增強了對隱私數據的保護,要對隱私數據權限作一個適配,iOS10調用相機,訪問通信錄,訪問相冊等都要在info.plist中加入權限訪問描述,否則以前大家的項目涉及到這些權限的地方就會直接crash掉。


解決辦法: 只須要在info.plist添加NSContactsUsageDescriptionkey, 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

3.四、跳轉到app內的隱私數據設置頁面

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];
    }
}
複製代碼

跳轉目的地

  • iOS系統版本 <= iOS7 , 只能跳轉到 系統設置頁面
  • iOS系統版本 >= iOS8 ,支持跳轉到第三方應用的設置界面中。使用prefs:root=bundleID ,bundleID是你第三方應用工程的惟一ID
  • iOS系統版本 >= iOS10,支持跳轉到本身應用設置,不支持跳轉到系統設置

3.五、字體變化

蘋果的默認字體會隨着iOS系統版本的不一樣而不一樣,iOS10中字體變大了。致使了原來的顯示有問題,會形成...的出現。暫時沒有好的解決辦法,須要本身在一個個適配一下!

3.六、UICollectionViewCell的的優化

  • 在iOS 10 以前,cell只能從重用隊列裏面取出,再走一遍生命週期,並調用cellForItemAtIndexPath建立或者生成一個cell.

  • 在iOS 10 中,系統會cell保存一段時間,也就是說當用戶把cell滑出屏幕之後,若是又滑動回來,cell不用再走一遍生命週期了,只須要調用willDisplayCell方法就能夠從新出如今屏幕中了.

  • iOS 10 中,系統是一個一個加載cell的,二之前是一行一行加載的,這樣就能夠提高不少性能;

  • iOS 10 新增長的Pre-Fetching預加載

3.七、UIRefreshControl

在iOS 10 中, UIRefreshControl能夠直接在UICollectionView和UITableView中使用,而且脫離了UITableViewController.如今RefreshControl是UIScrollView的一個屬性.

3.八、UserNotifications(用戶通知)

  • iOS 10全部相關通知被統一到了UserNotifications.framework框架中。增長了撤銷、更新、中途還能夠修改通知的內容。通知不在是簡單的文本了,能夠加入視頻、圖片,自定義通知的展現等等。

  • iOS 10相對以前的通知來講更加好用易於管理,而且進行了大規模優化,對於開發者來講是一件好事。

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

4、iOS9(Xcode7)

4.一、Bitcode

Xcode7 默認啓用 Bitcode,可是若是咱們用到的第三方庫編譯時還沒啓用 Bitcode,主工程就會編譯不過。Bitcode 是蘋果 App Thinning 的機制之一,能夠減小安裝包的大小。App store 會將這個 Bitcode 編譯爲可執行的64位或32位程序。

解決辦法一: 最簡單的解決辦法是先把 Bitcode 關掉:把 Build settings - Build Options - Enable Bitcode 改成 NO。

解決辦法二: 移除不支持BitCode的平臺SDK,或者尋找支持BitCode的替代品,或者聯繫SDK方支持BitCode。

4.二、HTTP 請求失敗

iOS9 默認不支持 HTTP 請求,須要改用更安全的 HTTPS(默認用 TLS 1.2)。蘋果還提供了配置,使得全部安全性更低的網絡請求也能使用,解決方案就是在 info.plist 裏面增長如下配置:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
複製代碼

若是複雜一些,還能夠指定白名單域名,聲明所支持 TLS 的最低版本。另外須要注意的是,即便寫了上述配置,在 HTTPS 頁面中,HTTP 的 javascript 或 css 不會被加載,由於蘋果認爲這下降了頁面的安全性。

4.三、canOpenUrl 限制

canOpenUrl 能夠用來判斷用戶是否安裝了某個 APP。也許是出於用戶隱私的考慮,iOS9 上對 canOpenUrl 作了限制,最多隻能對 50 個 scheme 作判斷。若是是用 Xcode7 編譯,須要在 plist 裏面聲明這些 scheme,沒有聲明的會直接返回 NO:

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>weixin</string>
    <string>wechat</string>
</array>
複製代碼

4.四、UIStatusBar的問題

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]
複製代碼

參考資料:

iOS12適配

iOS12AdaptationTips

關於iPhone X 的適配

iOS11適配iPhoneX總結

iOS 10 適配知識點總結

聊聊iOS 10更新之後跳轉系統設置的幾種方式

iOS 10 調用系統"設置"裏的功能(全)

iOS TouchID驗證和Keychain結合使用

iOS10AdaptationTips

適配iOS9

微信 iOS 9 適配總結

iOS9AdaptationTips

相關文章
相關標籤/搜索