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

相关文章
相关标签/搜索