iOS12、iOS11、iOS10、iOS9常见适配
作者:花丶满楼
链接:https://juejin.im/post/5c49a7d0518825254e4d46fc
一、iOS12(Xcode10)
1.1、升级Xcode10后项目报错
不允许多个info.plist
Xcode10是默认选中的最新的New Build System(Default),在这个编译系统的环境下,不允许多个info.plist
解决办法一:(推荐)
把build system切换到 Legacy Build System,换言之就是切换成老的编译系统,就OK了。
Xcode->File->Project Settings-> Build System -> Legacy Build System.
解决办法二:
删除其他info.plist文件。
iOS 12移除了libstdc++, 用libc++替代
Xcode10中libstdc++相关的3个库(libstdc++、libstdc++.6、libstdc++6.0.9)应该都是被彻底废弃了,如果你使用的三方库中有依赖,请尽快和提供方沟通,告知他们迁移吧。如果自己开发使用,也尽快考虑迁移的事宜吧。
1.2、iPhone XR不支持3D-Touch
OC检测代码
if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {
}
swift检测代码
self.traitCollection.forceTouchCapability == .availible
二、iOS11(Xcode9)
2.1、安全区域(SafeArea)
iOS11为UIViewController和UIView增加了两个新的属性safeAreaInsets和safeAreaLayoutGuide
safeAreaInsets 适用于手动计算.
safeAreaLayoutGuide 适用于自动布局.
UIViewController中新增:
- (void)viewSafeAreaInsetsDidChange;
UIView中新增:
- (void)viewSafeAreaInsetsDidChange;
在Storyboard使用Safe Area最低只支持iOS9,iOS8的用户就要放弃了
当UIViewController调用- (void)viewDidLoad时它的所有子视图的safeAreaInsets属性都等于UIEdgeInsetsZero。
viewSafeAreaInsetsDidChange的调用时机如下:
1、viewDidLoad
2、viewWillAppear
3、viewSafeAreaInsetsDidChange
4、viewWillLayoutSubviews
5、viewDidAppear
只有在调用viewSafeAreaInsetsDidChange后,才能获得view以及viewController的SafeArea(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.2、UIScrollView
iOS 11废弃了UIViewController的automaticallyAdjustsScrollViewInsets属性,新增了contentInsetAdjustmentBehavior属性,所以当超出安全区域时系统自动调整了SafeAreaInsets,进而影响了adjustedContentInset,在iOS11中决定tableView内容与边缘距离的是adjustedContentInset,所以需要设置UIScrollView的contentInsetAdjustmentBehavior属性。
// 方式一:(不推荐)修改额外的安全区域
if (@available(iOS 11.0, *)) {
self.additionalSafeAreaInsets = UIEdgeInsetsMake(-, , , );
}
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.3、tableview问题
iOS11开始UITableView开启了自动估算行高,estimatedRowHeight estimatedSectionHeaderHeight estimatedSectionFooterHeight三个高度估算属性由默认的0变成了UITableViewAutomaticDimension,如果不实现-tableView: viewForFooterInSection: 和 -tableView: viewForHeaderInSection:,那么estimatedRowHeight estimatedSectionHeaderHeight estimatedSectionFooterHeight三个高度估算属性由默认的0变成了UITableViewAutomaticDimension,导致高度计算不对,会产生空白。解决方法是实现对应方法或吧这三个属性设为0。
2.4、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;
}
}
}];
}</localauthentication>
2.5、启动图的适配
方法一:通过LaunchScreen.storyboard方式启动
方法二:使用Assets中的LaunchImage
给Brand Assets添加一张11252436大小的图片
打开Assets.xcassets文件夹,找到Brand Assets
右键Show in Finder
添加一张11252436大小的图片
修改Contents.json文件,添加如下内容
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "2436h",
"filename" : "1125_2436.png",
"minimum-system-version" : "11.0",
"orientation" : "portrait",
"scale" : "3x"
}
2.6、定位相关
在 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。
三、iOS10(Xcode8)
3.1、(Why?Safe!)插件取消
Xcode8取消了三方插件(很多优秀的插件,本来可以显著提高效率)的功能,使用Extension代替
Xcode 8 Extension 推荐
3.2、证书问题
为了方便用户来管理,提供Automatically manage signing。需要输入开发者账号!如果没有账号也没关系,在下面也可以选择Debug、Realease、inHouse模式下对应的证书也可以!
3.3、隐私数据访问问题
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>
3.4、跳转到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.5、字体变化
苹果的默认字体会随着iOS系统版本的不同而不同,iOS10中字体变大了。导致了原来的显示有问题,会造成…的出现。暂时没有好的解决办法,需要自己在一个个适配一下!
3.6、UICollectionViewCell的的优化
在iOS 10 之前,cell只能从重用队列里面取出,再走一遍生命周期,并调用cellForItemAtIndexPath创建或者生成一个cell.
在iOS 10 中,系统会cell保存一段时间,也就是说当用户把cell滑出屏幕以后,如果又滑动回来,cell不用再走一遍生命周期了,只需要调用willDisplayCell方法就可以重新出现在屏幕中了.
iOS 10 中,系统是一个一个加载cell的,二以前是一行一行加载的,这样就可以提升很多性能;
iOS 10 新增加的Pre-Fetching预加载
3.7、UIRefreshControl
在iOS 10 中, UIRefreshControl可以直接在UICollectionView和UITableView中使用,并且脱离了UITableViewController.现在RefreshControl是UIScrollView的一个属性.
3.8、UserNotifications(用户通知)
iOS 10所有相关通知被统一到了UserNotifications.framework框架中。增加了撤销、更新、中途还可以修改通知的内容。通知不在是简单的文本了,可以加入视频、图片,自定义通知的展示等等。
iOS 10相对之前的通知来说更加好用易于管理,并且进行了大规模优化,对于开发者来说是一件好事。
iOS 10开始对于权限问题进行了优化,申请权限就比较简单了(本地与远程通知集成在一个方法中)。
四、iOS9(Xcode7)
4.1、Bitcode
Xcode7 默认启用 Bitcode,但是如果我们用到的第三方库编译时还没启用 Bitcode,主工程就会编译不过。Bitcode 是苹果 App Thinning 的机制之一,可以减少安装包的大小。App store 会将这个 Bitcode 编译为可执行的64位或32位程序。
解决办法一:
最简单的解决办法是先把 Bitcode 关掉:把 Build settings - Build Options - Enable Bitcode 改为 NO。image.png
解决办法二:
移除不支持BitCode的平台SDK,或者寻找支持BitCode的替代品,或者联系SDK方支持BitCode。
4.2、HTTP 请求失败
iOS9 默认不支持 HTTP 请求,需要改用更安全的 HTTPS(默认用 TLS 1.2)。苹果还提供了配置,使得所有安全性更低的网络请求也能使用,解决方案就是在 info.plist 里面增加以下配置:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true>
</true></dict>
如果复杂一些,还可以指定白名单域名,声明所支持 TLS 的最低版本。另外需要注意的是,即使写了上述配置,在 HTTPS 页面中,HTTP 的 javascript 或 css 不会被加载,因为苹果认为这降低了页面的安全性。
4.3、canOpenUrl 限制
canOpenUrl 可以用来判断用户是否安装了某个 APP。也许是出于用户隐私的考虑,iOS9 上对 canOpenUrl 做了限制,最多只能对 50 个 scheme 做判断。如果是用 Xcode7 编译,需要在 plist 里面声明这些 scheme,没有声明的会直接返回 NO:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>weixin</string>
<string>wechat</string>
</array>
4.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适配 https://www.jianshu.com/p/56d7f9cec66d
iOS12AdaptationTips https://github.com/ChenYilong/iOS12AdaptationTips
关于iPhone X 的适配 https://www.lee1994.com/guan-yu-iphone/
iOS11适配iPhoneX总结 https://www.jianshu.com/p/d8073367c274
iOS 10 适配知识点总结 https://www.jianshu.com/p/61b73ac8662a
聊聊iOS 10更新以后跳转系统设置的几种方式 https://segmentfault.com/a/1190000007097444
iOS 10 调用系统"设置"里的功能(全) https://www.jianshu.com/p/d56ebc7b3646
iOS TouchID验证和Keychain结合使用 https://blog.csdn.net/xinxisxx/article/details/77967184
iOS10AdaptationTips https://github.com/ChenYilong/iOS10AdaptationTips
适配iOS9 https://blog.csdn.net/Kerry_Deng/article/details/48790909
微信 iOS 9 适配总结 https://www.infoq.cn/article/wechat-ios9-adaptation
iOS9AdaptationTips https://github.com/ChenYilong/iOS9AdaptationTips
iOS12、iOS11、iOS10、iOS9常见适配的更多相关文章
- iOS9网络适配(ATS)
[转]iOS9 new_001:iOS9网络适配(ATS) 下载Xcode7打开APP后大家都发现自己的APP无法联网了,why? 苹果官方文档介绍如下: App Transport Security ...
- iOS-pthread && NSThread && iOS9网络适配
几个概念: 进程:"正在运行"应用程序(app)就是一个进程,它至少包含一个线程: 进程的作用:为应用程序开辟内存空间: 线程:CPU调度的最小单元: ...
- iOS10 SiriKit QQ适配详解
原文连接 1. 概述 苹果在 iOS10 开放了 SiriKit 接口给第三方应用.目前,QQ已经率先适配了 Siri 的发消息和打电话功能.这意味着在 iOS10 中你可以直接告诉 Siri 让它帮 ...
- 【腾讯Bugly干货分享】iOS10 SiriKit QQ适配详解
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57ece0331288fb4d31137da6 1. 概述 苹果在iOS10开放 ...
- ios9+xcode7 适配笔记
升级了xcode7,最近ios9上马,又到了草泥马的时间,apple开放团队每次系统更新,都是无数个草泥马的适配夜晚,现在ios9上线以前的app竟然启动crash,这是要闹哪样. 1.微信和微博的s ...
- 58 同城 iOS 客户端 iOS11 及 iPhone X 适配实践
一.前言 前段时间 WWDC 大会上苹果推出了 iOS11 系统 和 iPhone X 新机型,相信各个 iOS 团队的开发者都已经在计划新系统和新机型的适配工作了.不得不说,新系统和新机型的发布确实 ...
- iOS11 与 iPhone X适配的那些坑(持更中...)
目录 问题列表 1.适配iPhoneX 屏幕原则 2.适配过程一些常量的设置 3..iPhone X 上运行有黑色区域问题 4.iOS11导航栏适配 5.出现UIScrollview 漂移问题(基本都 ...
- iOS9的适配
1.大部分社交平台接口不支持https协议. 问题描述:在iOS9下,系统默认会拦截对http协议接口的访问,因此无法获取http协议接口的数据.对ShareSDK来说,具体表现可能是,无法授权.分享 ...
- iOS10和Xcode8适配
1 Xib文件的注意事项 使用Xcode8打开xib文件后,会出现下图的提示. 大家选择Choose Device即可. 之后大家会发现布局啊,frame乱了,只需要更新一下frame即可.如下图 注 ...
随机推荐
- Unity 对象的批处理
本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/52813834 作者:car ...
- fsync体会
看这个链接:http://www.postgresql.org/docs/9.1/static/runtime-config-wal.html 是这样说的: fsync (boolean) If th ...
- 通过py2exe打包python程序的过程中,解决的一系列问题
py2exe的使用方法参考<py2exe使用方法>. 注:程序可以在解释器中正常运行,一切问题都出在打包过程中. 问题1: 现象:RuntimeError: maximum recursi ...
- 台湾ML笔记--1.2 formalize the learning probelm
Basic notations input: x∈χ (customer application) output: y∈y (good/bad after approving cred ...
- spring location设置本地路径
<context:property-placeholder location="file:D:/jdbc.properties"/> 直接在路径前加上 file:
- Spring Cloud 自定义ConfigServer 解决敏感信息存储问题
公司需要将系统配置信息中的敏感信息独立存放. 现有系统采用Spring Cloud Config提供配置信息,其中敏感信息主要是Db配置,分解本次需求: (1)数据库配置信息分离(主要是Db信息). ...
- 有关于PHP的基础知识
(1) l 长字符串表示,必须放在“<<<heredoc”和 “heredoc;”之间.主要是<<<,其次是也可以不使用heredoc. l “<< ...
- PAT 1055 集体照
https://pintia.cn/problem-sets/994805260223102976/problems/994805272021680128 拍集体照时队形很重要,这里对给定的 N 个人 ...
- 【Solr】——Solr7安装教程
前提 solr已经升级7.1,但是我们公司的solr还是使用的4.4,你们说low不low!!!重要的是,人家花费了大气将solr升级,从技术的角度来说solr7比solr4那是翻天覆地的改变! so ...
- 微信小程序开发中怎么设置转发(分享)的信息
如果什么都不设置,转发时默认名称是小程序的名称,转发的图片显示的是当前页面的截图,如图一 如何在自定义转发信息呢? 在进行转发的页面中: Page({ onShareAppMessage: funct ...