食用指南
Xcode 8带着Swift 3风风火火的到来了,作为一个平时使用OC为主的iOS开发来说,Swift 3正式和OC-like语法划定了界限。您可以简单浏览本文,也可以把本文当做从Swift2.2迁移到Swift3的指南。如果您在迁移的过程中遇到了问题,不妨直接CTRL+F
来搜索一下本文,看能不能找到解决方法。
因为本文是作为公司的内部培训资料,所以如果您在阅读的时候发现了错误或者是有更好的解决方法,欢迎联系我或者在下方留下您的评论。
1.苹果官方提供的Swift 3 更新内容(部分Objective-C语法也变更了)
1.1 语法上的形式变更
语法形式上的变更是非常方便理解的,在迁移过程中,Xcode会自动提示您转为对应的格式,形式变更的内容如下:
系统提供的枚举类型默认转为小写 比如
UIButton(type: .Custom)
->UIButton(type: .custom)
类型判断语法变化
object.dynamicType
->type(of: object)
UIViewController.statusBarStyle
->-(UIStatusBarStyle)preferredStatusBarStyle{}
Core Graphics API Swift化,基本来说这一部分能自动化就自动化转换,量太大了...
webview的代理方法
- (void)webView:(UIWebView *)webView didFailLoadWithError:(nullable NSError *)error
需要去掉nullable否则会报错
1.2 逃逸闭包必须显示声明
现在swift3.0所有的函数都是默认@noescape
非逃逸闭包,而 逃逸闭包(闭包在函数调用完之后才被调用的)必须显示声明@escaping
,比如:
func transport(requestMethod: Alamofire.HTTPMethod, url: String, callback: @escaping (Any) -> Void) -> Void {}
1.3 typealias 支持泛型
这带来了什么?更加抽象的CollectionType,甚至是更加便捷的JSON转模型方法
1.4 selector支持属性的getter和setter方法
class Dog {
var dogName: String
}
let dogNameGetter = #selector(getter: Dog.dogName)
1.5 Dispatch完全抛弃C-like 写法
是的,您的Snippet应该更新一下了!大部分旧写法都能找到新的写法替换,不过对于dispatch_once
来说就完全被废弃,您可以使用 懒加载 来替代。
DispatchQueue.global().async {
// 异步操作
DispatchQueue.main.async {
// 主线程操作
}
}
DispatchQueue.global().sync {
// 同步操作
}
//创建队列
let serialQueue = DispatchQueue(label: "Queuename")
//延迟执行
let delay = DispatchTime.now() + DispatchTimeInterval.seconds(\Seconds)
DispatchQueue.main.asyncAfter(deadline: delay) {
}
1.6引入系统版本判断代码
if #available(iOS 10.0,*){
//您的代码
}
1.7Any类型会逐渐开始使用
在Swift2的项目中,可能使用AnyObject
更加频繁,因为在Swift2 中编译器默认做了基本类型到OC类型的桥接。在Swift3中,这类桥接被废弃,所以需要明确Any和AnyObject的区别,也就是Any
包含AnyObject
,Any
类型包括struct、class、selector
等,而AnyObject
只对应class
2. iOS 10给迁移带来的其他需要注意点
2.1 2017年1月1日之前强制使用HTTPS
在iOS9中默认HTTP是被禁止的,可以在info.plist中通过设置NSAllowsArbitraryLoads
为YES
打开。新iOS 10如果要访问网络也可以如iOS 9 一样设置来访问网络,但是这在2017年1月1日之后有可能会被拒绝,您可以通过NSExceptionDomains
来针对特定域名开放HTTP访问。
2.2 隐私权限更严格了
iOS 10开始约束隐私权限了,如果您用到 相册、相机、位置、蓝牙、提醒事项、运动健康数据、麦克风、日历 等情况,您需要手动在info.plist
中添加权限请求说明。否则很大几率会闪退,This app has crashed because it attempted to access privacy-sensitive data without a usage description.
。
添加的字段名如下图所示:
2.3 默认不提供网络访问权限
iOS 10默认不提供网络访问,也就是说,刚刚进入应用,在用户没有点击“同意App访问蜂窝数据”之前是无法访问网络的。即使在用户点击确认之后,App往往没有设置自动刷新,用户体验很差的,希望您能注意一下。
2.4 字体变大,低版本显示正常的Label在iOS10中变成“...”
iOS10使用了新字体,文字的宽度变大了,之前如果是UILabel写死宽度或者定死宽度约束的很可能就会出现文字变成“...”,需要手动处理一下。UILabel大部分时候只需要给一个Origin Point就够了,文字的大小实际上不需要写死的。
2.5 推送需要明确打开Capability
在XCode7中这里的开关不打开,推送也是可以正常使用的,但是在XCode8中,这里的开关必须要打开,不然会报错
Error Domain=NSCocoaErrorDomain Code=3000 "未找到应用程序的“aps-environment”的授权字符串" UserInfo={NSLocalizedDescription=未找到应用程序的“aps-environment”的授权字符串}
打开后会在本地生成entitlements文件
3. Xcode 8给我们带来了哪些便利和麻烦
3.1 Xcode 8内置的Swift迁移工具
总的来说,这次迁移工具帮了很大的忙。如果您打开一个Swift 2工程,迁移会主动提示您打开了一个Swift 的旧工程,问您是不是要自动进行语法转换。本人建议您进行手工迁移,反正我是从来没有一次性迁移成功过的。手动迁移也没有特别麻烦,迁移工具在局部的语法提示会快速帮您定位需要迁移的位置。在我看来,自动迁移提示存在的目的在于帮您检测了集成的第三方库是不是也是用Swift 3语法写的。
3.2 Xcode 8完全不支持旧有的插件了
是的,完全不支持了,也不再支持Alcatraz
提供的插件,VVDocumenter、FuzzyAutocomplete、cocoapods-plugin
手动再见~~ Xcode官方的说法是为了安全考虑。的确,疯狂装插件在崩溃的时候要找到出问题的插件还是要花费一番功夫的。而且Xcode现在可以方便的开发编辑器插件了,只不过这些新插件的功能真心太弱了,太弱了...是的,我指的是,在座的各位新插件都是弱鸡。目前的解决办法是对Xcode进行重签名,然后生成一个“越狱版”的Xcode放在应用程序目录,教程链接地址在此。或者要不我们还是继续用Xcode 7.3.1吧...反正我是戒掉插件了。
3.3 Swift 2.3的使用
Xcode 7.3.1 是Swift 2.2 版本,而Xcode新建的工程默认都是基于Swift 3.0 的,如果您的工程是基于Swift2.3的版本的,您需要在Xcode 8.0 的 Build Settings
- Use Legacy Swift Language Version
中将参数的值设为Yes
,不过需要注意的是,如果是用Swift2.3的工程,第三方的工程也需要为Swift 2.3的版本,在您建立工程的时候,您应该提早确定您使用的第三方库是否支持Swift 2.3 。
3.4 Xcode 8现在支持图片文件名补全
Xcode 8现在支持图片文件名补全,在您键入UIImage(named: "ImageName")的时候会自动提示您工程中的图片,当然您也可以直接键入图片名称,即UIImage(named: "ImageName")
-> ImageName
, Xcode会在图片名称的前面建立一个小的缩略图,真的很小。
3.5 Xcode 8需要开启注释
如果遇到按CTRL + /
注释没有效果了,那可以在终端
里敲上~ sudo /usr/libexec/xpccachectl
,然后重启电脑试试。
3.6 Xcode 8疯狂打印一大堆Log
在工程Edit Scheme
中添加参数,如下图所示:
3.7 Xcode代码签名优化
总的来说是苹果帮您把签名管理起来了,就是一般不会出现Fix issue
的黄色小三角形了,没有特别需要我们做的。
3.8 旧版本的Xcode无法打开Xcode 8保存过的storyboard和xib了
因为新的Interface Builder添加了初始化界面的功能,默认打开旧有的storyboard和xib会询问您是否将所有视图设定为一个统一的尺寸,如果您点击确认,只需要更新一下frame
就可以看到结果,但是这在团队协作中会带来一个问题,在版本管理中,一旦push代码之后,团队中使用Xcode 8以下的成员就无法打开新版本的storyboard和xib了,解决方法是在Source Code
层面打开storyboard或者xib,手动删除
即可。
3.9 在Xcode中使用类似VVdocument的功能
快捷键:option + command + /
3.10 你可以每7天创建10个APP IDs
每个阶段能创建的App ID数量会有限制,你可以每7天创建10个APP IDs
4. 一些小的注意点
4.1 Cocoapod还是主力的包管理工具
可能您听说过SPM(Swift Package Manager),这个类似NPM的包管理工具在很早官方就发布消息说要支持了,但是实际应用中,很多第三方库目前并不支持(至少从目前来看),工具的使用远远没有Yarn
之于NPM
那样的平滑迁移,所以目前还是建议使用Cocoapod
或者是Carthage
吧!
4.2 RealmSwift 在Swift 3.0上要求进行数据库升级
准确的说,是当您将RealmSwift
升级到3.0能支持的版本之后,在操作数据库的时候要求您升级数据库。所以还是一步到位升级到3.0吧,别在2.3再折腾一遍了。
4.3 Alamofire 3.0不再支持iOS 8
反正我放个图:
4.4 Cocoapods 中强制使用 Swift 3 语法
只需要在Podfile中添加:
#swift 3 adapt
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['SWIFT_VERSION'] = '3.0'
end
end
end
4.5 获取特定branch、tag、仓库的第三方库
在刚刚开始适配Swift 3的阶段,会遇到相当多的问题,比如:
作者还没有到Cocoapods官方设置更新信息
作者将Swift 3的版本建立在其他分支上,默认支持的还是2.2或者是2.3的版本。
作者根本还没有支持Swift 3 ,不过有热心的网友建了一个自己的仓库,帮忙适配了一下
这时候您可以尝试在pod后面添加一些描述信息来定位到您真正想要获取到的库的位置,比如这里就把SwiftyJSON库的获取地址转到了IBM维护的一个仓库上:
pod 'SwiftyJSON',
:git => 'https://github.com/IBM-Swift/SwiftyJSON.git',
:branch => 'master'