iOS10和Xcode8踩坑记录

iOS10和Xcode8的GM版放出后,iOS10适配工作就非常重要了。Xcode8下完打开项目后就陆续碰到了一些坑,本文对此这些坑做一些记录。

无法打开的xib和storyboard

由于同事们还在Xcode7.3上开发,然而你用Xcode8打开xib或storyboard后,会弹出一个选择机型的框,如果想要用Xcode8改xib或storyboard,就必须chosse
ios10-and-xcode8-adapt00

然而你chosse后,同事用7.3去打开这个xib或者storyboard你会发现,打不开了,这不是坑爹吗?
ios10-and-xcode8-adapt01

不过也可以通过source code去删除掉版本限制,不过建议还是不要这样做。
ios10-and-xcode8-adapt02

控制台的疯狂

控制台输出不相关信息

跑起项目后发现控制台在疯狂输出,根本无法看到自己的打印输出
ios10-and-xcode8-adapt03

需要EditScheme -> 左侧Run -> 右侧Arguments -> 下方Environment Variables -> 添加 OS_ACTIVITY_MODE = disable

ios10-and-xcode8-adapt04

ios10-and-xcode8-adapt05

真机调试打印显示不全(2016.10.24补充)

这几天调试时发现,使用Xcode8+iOS10调试时,首先是真机输出打印不输出,后面发现是因为上面设置的OS_ACTIVITY_MODE = disable影响到了打印输出,取消这个设置后后虽然能打印了。

但是又出现一个新问题:在iOS10真机调试打印请求回调的json居然截断了(显示不全),但是Xcode8+iOS9却正常,经过一番查询,解决办法是在pch里用printf重新定义一下NSLog。

具体代码如下:

1
2
3
4
5
6
7
8
9
10
#define NSLog(format, ...) \
do { \
printf("\n<%s : %d : %s>-: %s", \
[[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], \
__LINE__, \
__FUNCTION__, \
[[NSString stringWithFormat:format, ##__VA_ARGS__] UTF8String]); \
} while(0)
#else
#define NSLog(format, ...) do{ } while(0)

注释失效了😱

终端来一发sudo /usr/libexec/xpccachectl然后重启

新增的文档注释

Xcode8里加入了喵神的文档注释,但是貌似功能没有之前插件的强,新的文档注释使用快捷键Option + Command + /
ios10-and-xcode8-adapt06

ios10-and-xcode8-adapt07

不过这个文档注释并不能像喵神的插件一样随意使用,如下图的时候就报提示没找到需要进行文档注释的东西😂
ios10-and-xcode8-adapt08

label显示不全

详见上一篇 iOS10的label文字显示不全问题

相机、相册、定位…各种崩

在排查上个label显示不全问题的时候,发现调相机崩了,调相册崩了,调定位又崩了,但是xcode7打的包在iOS10手机安装使用却是正常,什么👻

这次Xcode8对调用各种隐私权限做了控制,在调试的时候,需要在info.plist里声明你的权限和对应的提示文案,比如相册权限
ios10-and-xcode8-adapt09

ios10-and-xcode8-adapt10

其他权限

可以在info.plist值看到所有Private - 开头的都是
ios10-and-xcode8-adapt11
ios10-and-xcode8-adapt12

xib和storyboard布局混乱

问题详述

使用Xcode8偶然打开了项目中的storyboard文件,然后跑起项目,却发现界面全乱了
ios10-and-xcode8-adapt13

造成原因

经过一番搜索后,发现Xcode8对xib和storyboard做出了一些修改,似的在awakeFromNibviewDidLoad方法中拿自己拖上去的控件的frame均变成了(0, 0, 1000, 1000),若直接在此使用控件frame进行二次修改,如:修改A控件的宽为B控件的一半,则B控件实际当前的宽是1000,就会造成混乱。解决办法是在使用原控件frame之前调一次layoutIfNeeded方法。

查证实践

  1. 使用Xcode7建一个项目,拖一个tableview和cell,给cell上拖一个imageview和一个label,并设置约束
    ios10-and-xcode8-adapt15

  2. 在viewController的viewDidLoad中打印调用layoutIfNeeded前后各元素的frame
    ios10-and-xcode8-adapt16

  3. 在cell的awakeFromNib调用layoutIfNeeded方法前后打印frame,并测试给cell赋值后是否frame也需要调用
    ios10-and-xcode8-adapt17

  4. 在Xcode7中运行,打印结果
    发现原在Xcode7时,viewDidLoadawakeFromNib中能获取正常的frame
    ios10-and-xcode8-adapt18

  5. 使用Xcode8,并点开storyboard后
    发现git修改记录中删除了很多标签的元素
    ios10-and-xcode8-adapt19

    在Xcode8中运行后,打印结果,发现viewDidLoadawakeFromNib中,执行layoutIfNeeded之前拖上去的控件的frame都变成了{0, 0, 1000, 1000},执行之后的frame是正常的,给cell赋值时的frame也是正常的。
    ios10-and-xcode8-adapt20

  6. 再次打开Xcode7, 使用source code模式删除storyboard中版本限制后,再以interface builder方式打开storyboard,发现size被设置成了inferred模式,而且各控件的值也是不对的。
    ios10-and-xcode8-adapt21

结论

在更新Xcode8后,并打开了某个xib/storyboard后,最好run下看看是不是乱了。如果乱了,就去对应的controller或cell看看是不是在viewDidLoadawakeFromNib中使用了控件的frame,如果使用了,请在使用前调用layoutIfNeeded方法。

如:之前我司项目中的布局乱了,确实是在awakeFromNib中利用控件的frame来修改某个控件的frame,于是就坑了。
ios10-and-xcode8-adapt22

然后,加上调用layoutIfNeeded后,就恢复如初了。
ios10-and-xcode8-adapt14

swift版本兼容问题

如果工程中使用了swift,则第一次使用xcode8打开时,会弹窗提示转换,也有可能不弹窗而且是编译的时候,报错,错误如下:

1
2
3
4
5
Use Legacy Swift Language Version” (SWIFT_VERSION) is
required to be configured correctly for targets which use Swift.
Use the [Edit > Convert > To Current Swift Syntax…] menu
to choose a Swift version or use the Build Settings editor to
configure the build setting directly.

如图:
ios10-and-xcode8-adapt23

实际上就是提示你去转换一下swift版本,因为在Xcode7.3.1时swift为2.2,而xcode8支持swift2.3或者swift3.0。如果是直接弹窗提示了,且你是纯swift工程或是自己写的siwft库,可以尝试转换一下,虽然可能他的修改建议不合适。如果是三方库是swift写的,可以考虑等待三方库更新。

解决方法

  1. 引入swift2.3/3.0的三方库 或者 自行修改之后,手动从Xcode菜单栏->Edit->Convert->To Current Swift Syntax…打开迁移引导。
    ios10-and-xcode8-adapt24

  2. 选择符合的swift版本
    ios10-and-xcode8-adapt25

  3. 勾选需要转换的framework或者工程
    比如:我司项目使用了一个swift库Charts,使用pod引入最新支持2.3的版本后,xcode8会报错让执行迁移引导,实际上勾选并点击next后,会提示不需要转换。(此图是已经进行过迁移引导后的截图,所以下方会提示已经转换成2.3的语法了)
    ios10-and-xcode8-adapt26

  4. 目前还有pod useFramework导致其他库.h文件找不到问题,还在尝试解决