@(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]
复制代码