原文: http://www.cnblogs.com/dsxniubility/p/4821184.html

整理iOS9适配中出现的坑(图文)

 

本文主要是说一些iOS9适配中出现的坑,如果只是要单纯的了解iOS9新特性可以看喵神的开发者所需要知道的 iOS 9 SDK 新特性。9月17日凌晨,苹果给用户推送了iOS9正式版,随着有用户陆续升级iOS9,也就逐渐的衍生出了一系列的问题,笔者也在赶忙为自己维护的App做适配,本文写的一些坑基本都是亲身体验了。

一、NSAppTransportSecurity

iOS9让所有的HTTP默认使用了HTTPS,原来的HTTP协议传输都改成TLS1.2协议进行传输。直接造成的情况就是App发请求的时候弹出网络无法连接。解决办法就是在项目的info.plist 文件里加上如下节点:

NSAppTransportSecurity - NSAllowsArbitraryLoads

这个子节点的意思是:是否允许任性的加载?! 设为YES的话就将禁用了AppTransportSecurity转而使用用户自定义的设置,这个问题就解决了。

如果你不是在董铂然博客园看到本文,请点击查看原文

上面说是苹果限制了HTTP协议,但是也并不是说所有的HTTPS都能完美适配iOS9了。

举个栗子,从app内起webView加载https的网页。新建个项目写几行起网页的代码

1
2
3
4
5
6
7
8
9
10
11
12
- (void)loadView{
    UIWebView *web = [[UIWebView alloc]initWithFrame:[UIScreen mainScreen].bounds];
    self.view = web;
}
- (void)viewDidLoad {
    [super viewDidLoad];
     
    UIWebView *web = (UIWebView *)self.view; //董铂然
    NSURL *url = [NSURL URLWithString:@"https://github.com/"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [web loadRequest:request];
}

中间的url就是我们想要加载的https地址,用https://baidu.com/ 和 https://github.com/ 分别试一下,结果不同

  

github的网页能打开,百度的网页打不开,下面打印了一行log

1
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)

原因是苹果的官方资料说首先必须要基于TLS 1.2版本协议。然后证书的加密的算法还需要达到SHA256或者更高位的RSA密钥或ECC密钥,如果不符合,请求将被中断并返回nil.

在浏览器中是可以直接查看这个网站的加密算法的,先点绿锁再点证书信息。

从右边两张图可以看出,github带RSA加密的SHA-256符合苹果的要求,所以才可以展示。

针对百度的情况可以在info.plist中配置如下,如果网站引用的比较多应该是需要针对每个网站进行配置。

NSAppTransportSecurity,NSExceptionDomains,NSIncludesSubdomains,NSExceptionRequiresForwardSecrecy,NSExceptionAllowInsecureHTTPLoads 写在下面便于复制。

其中的ForwardSecrecy理解为超前的密码保护算法,在官方资料里有写,一共是11种。配置完毕百度可以访问。

   

二、Bitcode

bitcode的理解应该是把程序编译成的一种过渡代码,然后苹果再把这个过渡代码编译成可执行的程序。bitcode也允许苹果在后期重新优化我们程序的二进制文件,有类似于App瘦身的思想。

用了xcode7的编译器编译之前没问题的项目可能会出现下列报错。

1
XXXX’ does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64

问题的原因是:某些第三方库还不支持bitcode。要不然是等待库的开发者升级了此项功能我们更新库,要不就是把这个bitcode禁用。

禁用的方法就是找到如下配置,选为NO.(iOS中bitcode是默认YES,watchOS中bitcodes是不让改的必须YES。)

三、设置信任

这一条只和企业级应用或inhose 有关,和AppStore渠道的应用无关。

在iOS8只是弹出一个窗问你是否需要让手机信任这个应用,但是在iOS9却直接禁止,如果真的想信任需要自己去手动开启。类似于Mac系统从未知开发者处下载的dmg直接打不开,然后要到系统偏好设置的安全性与隐私手动打开。 下图展示左边iOS8,右边iOS9

 

用户需要去 设置---》通用---》描述文件 里面自行添加信任。

这种问题的处理方法也就两种:1.提前周知暂时不要升级iOS9  2.大多是公司员工使用的企业级应用,群发一个指导邮件。

四、字体

iOS8中,字体是Helvetica,中文的字体有点类似于“华文细黑”。只是苹果手机自带渲染,所以看上去可能比普通的华文细黑要美观。iOS9中,中文系统字体变为了专为中国设计的“苹方” 有点类似于一种word字体“幼圆”。字体有轻微的加粗效果,并且最关键的是字体间隙变大了!

所以很多原本写死了width的label可能会出现“...”的情况。

 iOS8

 iOS9 蛋疼

上面这两张图也可以直观的看出同一个界面,同一个label的变化。

所以为了在界面显示上不出错,就算是固定长度的文字也还是建议使用sizetofit 或者ios向上取整 ceilf() 或者提前计算

1
2
CGSize size = [title sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:14.0f]}];
CGSize adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height));

五、URL scheme

URL scheme一般使用的场景是应用程序有分享或跳其他平台授权的功能,分享或授权后再跳回来。

在iOS8并没有做过多限制,但是iOS9需要将你要在外部调用的URL scheme列为白名单,才可以完成跳转

如果iOS9没做适配 会报如下错误

1
canOpenURL: failed for URL : "mqzone://qqapp" - error: "This app is not allowed to query for scheme mqzone"

具体的解决方案也是要在info.plist中设置 LSApplicationQueriesSchemes 类型为数组,下面添加所有你用到的scheme

六、statusbar

这个还好只是报一个警告,如果就是不管他,也不会出现问题。

1
<Error>: CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.

以前我们为了能够实时的控制顶部statusbar的样式,可能会在喜欢使用

1
2
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]
[[UIApplication sharedApplication]setStatusBarHidden:YES];

但是这么做之前需要将 info.plist 里面加上View controller-based status bar appearance  BOOL值设为NO,就是把控制器控制状态栏的权限给禁了,用UIApplication来控制。但是这种做法在iOS9不建议使用了,建议我们使用吧那个BOOL值设为YES,然后用控制器的方法来管理状态栏比如。

1
2
3
4
- (UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

点进头文件可以验证刚才说法:

1
@property(readwritenonatomic,getter=isStatusBarHidden) BOOL statusBarHidden NS_DEPRECATED_IOS(2_0, 9_0, "Use -[UIViewController prefersStatusBarHidden]");

七、didFinishLaunchingWithOptions

如果运行的时候报下列错误,那就是你的didFinishLaunchingWithOptions写的不对了

1
***** Assertion failure in -[UIApplication _runWithMainScene:transitionContext:completion:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3505.16/UIApplication.m:3294**

iOS9不允许在didFinishLaunchingWithOptions结束了之后还没有设置window的rootViewController。 也许是xcode7的编译器本身就不支持。

解决的方法当然就是先初始化个值,之后再赋值替换掉

1
2
UIWindow *window = [[UIWindowalloc] initWithFrame:[UIScreenmainScreen].bounds];
window.rootViewController = [[UIViewController alloc]init];

八、tableView

虽然现在的iOS9已经推送正式版了,但是iOS9使用时还是会感觉到App比以前更加卡顿了,tableView拖动时卡顿显示的最为明显。 并且之前遇到一个bug,原本好的项目用xcode7一编译,tableView刷新出了问题 ,[tableView reloadData]无效 有一行cell明明改变了但是刷新不出来。 感觉可能是这个方法和某种新加的特性冲突了,猜测可能是reloadData的操作被推迟到下一个RunLoop执行最终失效。

解决的方法是,注释[tableView reloadData],改用局部刷新,问题居然就解决了。

1
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];

九、NSLocalizableString(XCode7问题)

如果你程序启动后出现主页面一片空白,或是报了以下的栈调用错误。那就是NSLocalizableString的死循环导致堆栈溢出了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#0  0x003052a8 in -[NSLocalizableString length] ()
#1  0x003052cc in -[NSLocalizableString length] ()
#2  0x003052cc in -[NSLocalizableString length] ()
#3  0x003052cc in -[NSLocalizableString length] ()
#4  0x003052cc in -[NSLocalizableString length] ()
#5  0x003052cc in -[NSLocalizableString length] ()
#6  0x003052cc in -[NSLocalizableString length] ()
#7  0x003052cc in -[NSLocalizableString length] ()
#8  0x003052cc in -[NSLocalizableString length] ()
#9  0x003052cc in -[NSLocalizableString length] ()
#10 0x003052cc in -[NSLocalizableString length] ()
#11 0x003052cc in -[NSLocalizableString length] ()
#12 0x003052cc in -[NSLocalizableString length] ()
#13 0x003052cc in -[NSLocalizableString length] ()
#14 0x003052cc in -[NSLocalizableString length] ()
#15 0x003052cc in -[NSLocalizableString length] ()
#16 0x003052cc in -[NSLocalizableString length] ()

这个的解决方法就是找到特定的页面,然后将English 前面的勾勾上。

十、bundle identifier(Xcode7问题)

如果你遇到了在本地编译通过,但是在CI上打包失败。并且报的错误是和bundle identifier相关,那很有可能是你plist文件中写的bundle identifier没有起作用。

因为xcode7新增了此功能,在target下面的BuildSetting里面增加了Product Bundle identifier。苹果之后的做法应该是推荐在此处设置bundle identifier,此处的设置会比info.plist里面优先读取。

如果你的Bundle identifier一直没变,可能不会发现此问题。如果改变了,你在plist中修改是无效的。

另一个做法就是在ci打包的配置Execute shell上增加以下代码

1
"Set :CFBundleIdentifier com.XXX.XXX" "XXX/Supporting Files/XXX-Info.plist"

十一、 ActionSheet

Actionsheet 在iOS8的时候改了一次版,当时是和AlertView二合一,并且以AlertViewController作为载体,之后再present出来,这在当时,苹果应该是想统一各个控件的展示方式,但是很多人可能并没有在意因为直接show那个方法并没有废除,大家都觉得应该是新旧都能用,再加上有的公司可能自己还做了一定扩展,诸多原因导致还是用的旧方法。

在iOS9上使用旧方法直接show,会出现左图的问题。如果用的是AlertViewController的方法则不会出现问题(右图)

    

我猜测可能是sheet的windowLevel比键盘低导致的。但是将优先级设到10000,然后显示在keyWindow上。

1
2
sheet.window.windowLevel = 10000;
[sheet showInView:[UIApplication sharedApplication].keyWindow];

然后没有效果,然后又查了下stackoverflow 有个方法能取出优先级最高的window

1
2
3
UIWindow *topWindow = [[[UIApplication sharedApplication].windows sortedArrayUsingComparator:^NSComparisonResult(UIWindow *win1, UIWindow *win2) {
    return win1.windowLevel - win2.windowLevel;
}] lastObject];

试了下还是没有效果。 应该键盘的优先级无论如何都是最高的, 想盖在键盘上面的方法行不通。

当然,如果更换的成本比较大,也并不是没有办法,直接设置弹sheet之前收回键盘就好了。

如果你不是在董铂然博客园看到本文,请点击查看原文

暂时遇到这些问题,感觉iOS9的出现让所有iOS开发都是菊花一紧,预祝所有的iOS都能及时的做好适配改完bug,下个版本一上线,所有问题都解决。

 

整理iOS9适配中出现的坑(图文)的更多相关文章

  1. 整理iOS9适配中出现的坑

    一.NSAppTransportSecurity iOS9让所有的HTTP默认使用了HTTPS,原来的HTTP协议传输都改成TLS1.2协议进行传输.直接造成的情况就是App发请求的时候弹出网络无法连 ...

  2. 整理 iOS 9 适配中出现的坑(图文)(转)

    作者:董铂然 本文主要是说一些iOS9适配中出现的坑,如果只是要单纯的了解iOS9新特性可以看瞄神的开发者所需要知道的 iOS 9 SDK 新特性.9月17日凌晨,苹果给用户推送了iOS9正式版,随着 ...

  3. 整理 iOS 9 适配中出现的坑(图文)

    作者:董铂然 授权本站转载. 本文主要是说一些iOS9适配中出现的坑,如果只是要单纯的了解iOS9新特性可以看瞄神的开发者所需要知道的 iOS 9 SDK 新特性.9月17日凌晨,苹果给用户推送了iO ...

  4. 整理 iOS 9 适配中出现的坑

    本文主要是说一些iOS9适配中出现的坑,如果只是要单纯的了解iOS9新特性可以看瞄神的开发者所需要知道的 iOS 9 SDK 新特性.9月17日凌晨,苹果给用户推送了iOS9正式版,随着有用户陆续升级 ...

  5. iOS 9 适配中出现的坑

    整理 iOS 9 适配中出现的坑(图文) 2015-10-22 iOS开发 库克表示:“现在在中国有150多万的开发者在iOS当中开发应用程序,我们鼓励更多的人开发应用程序,也鼓励更多的创业加入.” ...

  6. 整理iOS9适配

    整理iOS9适配 本文主要是说一些iOS9适配中出现的坑,如果只是要单纯的了解iOS9新特性可以看瞄神的开发者所需要知道的 iOS 9 SDK 新特性.9月17日凌晨,苹果给用户推送了iOS9正式版, ...

  7. iOS9适配中出现的一些常见问题

    本文主要是说一些iOS9适配中出现的坑,如果只是要单纯的了解iOS9新特性可以看瞄神的开发者所需要知道的 iOS 9 SDK 新特性.9月17日凌晨,苹果给用户推送了iOS9正式版,随着有用户陆续升级 ...

  8. iOS9适配中的各种问题

    1.http在ios9上不能在使用.需要进行配置. the resource could not be loaded because the app transport security policy ...

  9. 整理下react中常见的坑

    其实有些也不能算是坑,有些是react的规定,或者是react的模式和平常的js处理的方式不同罢了 1.setState()是异步的this.setState()会调用render方法,但并不会立即改 ...

随机推荐

  1. windows 环境下的redis安装

    Redis安装 1.由于是练习,所以就在windows下安装的环境,并没有在LINUX服务器上装,但是知识点是一样的 安装流程: a.下载地址:https://github.com/MSOpenTec ...

  2. BZOJ1081[SCOI2005]超级格雷码

    Description 著名的格雷码是指2n个不同n位二进制数(即0~2n-1,不足n位在前补零)的一个排列,这个排列满足相邻的两个二进制数的n位数字中最多只有一个数字不同(例如003和001就有一个 ...

  3. 在Linux中如何使用命令进行RS-232串口通信和数据包解析

    文章首发于浩瀚先森博客 1. 获取串口号 在Linux系统中一切皆为文件,所以串口端口号也不例外,都是以设备文件的形式出现.也就是说我们可以用访问文本文件的命令来访问它们. a. 一般串口都是以/de ...

  4. Codeforces Round #381(div 2)

    A.(分类讨论) 题意:你有n本书,有三种买书方案,花a元买1本,花b元买2本,花c元买3本,问最少花多少钱,使得你书的总数是4的倍数 分析:分类讨论的题,但是要注意你可以买超过4本书--可以买5本. ...

  5. bzoj3731: Gty的超级妹子树

    一代神题啊orz(至少是以前年代的神题吧) 块状树 复杂度nsqrtnlogn 真是exciting 还没有卡时限 话不多说直接上代码 (最近解锁了记事本写代码的技能...感觉越来越依赖OJ调试了.. ...

  6. Java的多线程机制系列:(二)缓存一致性和CAS

    一.总线锁定和缓存一致性 这是两个操作系统层面的概念.随着多核时代的到来,并发操作已经成了很正常的现象,操作系统必须要有一些机制和原语,以保证某些基本操作的原子性.首先处理器需要保证读一个字节或写一个 ...

  7. HttpClient 4.3 使用

    httpclient的api变化很快,本篇随笔记录自己使用4.3.6版本时所做的设置.版本虽然不是最新,但达到了目的就行. maven依赖: <dependency> <groupI ...

  8. oneuijs/You-Dont-Need-jQuery

    oneuijs/You-Dont-Need-jQuery  https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh- ...

  9. Linux下通过脚本自动备份Oracle数据库并删除指定天数前的备份

    说明: Oracle数据库服务器操作系统:CentOSIP:192.168.0.198端口:1521SID:orclOracle数据库版本:Oracle11gR2 具体操作: 1.root用户登录服务 ...

  10. asp.net Literal

    常用于动态向页面添加内容 Panel panel = new Panel(); Literal literal = new Literal(); literal.Text = "<br ...