原文地址:http://blog.jiar.vip/2017/06/09/%E9%80%82%E9%85%8DXcode9-0-beta%E4%B8%8ESwift4.0/
简书地址:http://www.jianshu.com/p/1f702d59e54b
您能够经过保留原文地址或者简书地址的方式进行转载。html
这几天苹果在开WWDC2017
大会,期间放出了Xcode9.0-beta
以及Swift4
。为了响应苹果爸爸的号召,我果断下载了Xcode9.0-beta
,并在项目中拉出了新的分支,准备搞事。ios
Xcode9.0-beta
内置的Swift
版本不止一个,它同时支持Swift4.0
和Swift3.2
。而咱们正在用的Xcode8
,最高只支持Swift3.1
。基于这个事实,我先拉一个Xcode9.0-beta-Swift3.2
的分支,待适配好Swift3.2
后,再起分支Xcode9.0-beta-Swift4.0
去支持Swift4.0
。git
Swift3.2
首先,对于Swift3.2
,个人理解是:既然版本命名为3.2
,那么应该只是基于3.1
版本上的微调(我去查Swift
,查到更多的是关于Swift4.0
方面的信息)。适配Swift3.2
的过程当中,个人项目代码不须要任何改动,惟一出问题的是一个第三方库:Eureka,报错的缘由是Collection
协议的subscript
返回值从Array
变成了ArraySlice
,关于这个问题,已有人在Eureka的issues中提出(#1082)。随后有人commit修复了这个问题,并开出新分支来适配Swift3.2
。github
最后,我在Podfile
中修改pod 'Eureka'
为pod 'Eureka', :git => 'https://github.com/xmartlabs/Eureka.git', :branch => 'swift3.2'
,完成了适配Swift3.2
。swift
因而可知,适配Swift3.2
几乎是没有什么压力的,我也就看到Collection
协议的subscript
返回值变更这个状况。api
Swift4.0
并非全部库都能作到及时支持Swift4.0
,更况且是在如今连Xcode9
也仍是beta
的状态,因此咱们仅能作到将本身的业务代码(主工程代码)部分升级到Swift4.0
,而后同时保留各类pod
库在Swift3.2
版本。没办法,谁叫Swift4.0
也还没法作到ABI
兼容呢(希望能在Swift5
以前实现吧)。至于我说的同时使用两个版本的Swift
,这是没问题的,Xcode9
支持在项目中同时使用Swift3.2
和Swift4.0
。xcode
Swift
版本)第一步,以下图指定主工程的Swift
版本为4.0
第二步,以下所示,在Podfile
文件的最下方加入以下代码,指定pod
库的Swift
版本为3.2
(这样会使得全部的第三方pod
库的Swift
版本都为3.2
)微信
post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '3.2' end end end
从Swift3.2
到Swift4.0
的过程,比从Swift3.1
到Swift3.2
的过程要麻烦一点,可是比当年从Swift2.3
到Swift3
的过程要好太多了。app
下面我列举一下Swift3.2
到Swift4.0
的改变(只是我项目中遇到的):框架
Swift4.0
中对于扩展的属性(包括实例属性、static
属性、class
属性),都只能使用get
方法,不可以使用set
方法
Swift4.0
中再也不容许复写扩展中的方法(包括实例方法、static
方法、class
方法)
swift3
使用#selector
指定的方法,只有当方法权限为private
时须要加@objc
修饰符,如今全都要加@objc
修饰符
字体方面的一些重命名(NSFontAttributeName
重命名为NSAttributedStringKey.font
、NSForegroundColorAttributeName
重命名为NSAttributedStringKey.foregroundColor
、NSStrikethroughStyleAttributeName
重命名为NSAttributedStringKey.strikethroughStyle
、size(withAttributes:)
方法重命名为size(withAttributes:)
)
...
OC
与Swift4.0
混编才是坑因为历史缘由,我负责的项目,还有好大一部分OC
的代码,新写的Swift
须要被OC
调用。因此,问题来了...
OC
调用Swift4.0
问题一:编译不经过我在Swift4
的代码中写了很多class
和extension
,有些也给OC
调用。在OC
的代码中,咱们经过#import "ModuleName-Swift.h"
导入了Swift
文件,以给OC
调用。若是是Swift3.2
,一切都能正常工做,可是在Swift4.0
上,编译通不过了。
一:在OC
中调用一个Swift4.0
类的方法(包括实例方法、static
方法、class
方法),你须要:
在该Swift4.0
类前加上修饰符@objc
该Swift4.0
类必须继承NSObject
(不然,没法在前面加上修饰符@objc
。固然,这里指的是普通类,@objc
也是能够修饰UI
开头的一系列UIKit
框架下的UI
类,只是修饰了这些类,不会产生什么影响)
在须要调用的方法前加上修饰符@objc
示例以下:
@objc class SampleObject: NSObject { @objc func sampleFunc { print("sampleFunc") } @objc static func sampleStaticFunc { print("sampleStaticFunc") } @objc class func sampleClassFunc { print("sampleClassFunc") }
如此一来,即可在OC
文件中调用,示例以下:
#import "OCSample.h" #import "ModuleName-Swift.h" @implementation OCSample - (void)callSwiftFunc { // 调用实例方法 SampleObject *object = [[SampleObject alloc] init]; [object sampleFunc]; // 调用static方法 [SampleObject sampleStaticFunc]; // 调用class方法 [SampleObject sampleClassFunc]; } @end
二:在OC
中调用一个Swift4.0
扩展的属性(包括实例属性、static
属性、class
属性)、方法(包括实例方法、static
方法、class
法),你有以下两种选择方式:
在该Swift4.0
扩展前加上修饰符@objc
(这样的话,该扩展下的全部的属性、方法,均可被OC
调用)。
示例以下:
@objc extension UIViewController { var name: String { reutrn "name" } static var staticName: String { reutrn "staticName" } class var className: String { reutrn "className" } func nameFunc() { print("nameFunc") } static func staticNameFunc() { print("staticNameFunc") } class func classNameFunc() { print("classNameFunc") } }
在须要的属性、方法前直接加上@objc
修饰,也可达到目的。
示例以下:
extension UIViewController { @objc var name: String { reutrn "name" } @objc static var staticName: String { reutrn "staticName" } @objc class var className: String { reutrn "className" } @objc func nameFunc() { print("nameFunc") } @objc static func staticNameFunc() { print("staticNameFunc") } @objc class func classNameFunc() { print("classNameFunc") } }
OC
调用Swift4.0
问题二:运行时找不到属性这个问题藏得比较深,恰巧项目中有着相关的实现,让我看出发现这个潜在因素。
项目中有这么一种实现:有一个Swift4.0
的类,是继承UIViewController
的。而后我在OC
里面对这个继承而来的UIViewController
进行操做,我用了[viewController valueForKey:@"iconURL"]
这一KVC
方法去获取这个自定义UIViewController
中的iconURL
这一属性的属性值。这种方式,编译时是没法检查出问题的。可是在运行时,问题就来了,找不到这个属性。由于这个属性没有暴露给OC
来进行调用。
解决方式:仅须要在自定义的UIViewController
类中给须要暴露给OC
调用的属性前加上@objc
修饰符即可。如此一来,在OC
代码中就能访问到这个属性。(注意:这里可不像上面提到的extension
同样,在这个已定义的UIViewController
类前面加上@objc
修饰符没有任何意义)。
示例以下:
class SampleViewController: UIViewController { @objc var iconURL: String? }
除了在OC
里经过valueForKey:
方法调用到一些未通过@objc
修饰的Swift4.0
的UI
类的属性会致使crash
。其余好比你在Swift4.0
代码中,经过setValuesForKeys
这种经过KVC
来操做未通过@objc
修饰的属性,也会致使crash
。
更多关于混编方面的内容,能够访问查看Apple官方提供的这篇文章:Using Swift with Cocoa and Objective-C (Swift 4),篇幅很多,不仅仅介绍了Swift4.0
与OC
的混用,也介绍了与C
的api
的交互、还有更多关于@objc
修饰符的用法。
Xcode9-beta
的更多Xcode9-beta
局域网调试必须是Xcode9-beta
iPhone
系统需iOS11
以上
在Xcode9-beta
菜单的Window
选项中选择Devices and Simulators
经过链接线让你的Mac
识别到你的iPhone
在Devices and Simulators
面板的左侧Connected
菜单中选择链接的设备,而后在顶部的Devices
和Simulators
选项中选择Devices
(这里其实默认就是选择了Devices
),最后勾选Connect via network
选项。
本文为做者这几天在Xcode9-beta
以及Swift4.0
方面的学习记录与分享,做者会视状况对内容进行补充。
若是您在阅读本文中发现内容存在错误,但愿您积极指出。若是您有其余建议,也欢迎在评论去区留言。
做者接受指正,可是但愿彼此之间保留敬意。
欢迎转载,但请保留博文的原地址或者博文在简书上的地址。
比起 微博@Jiar ,更喜欢 推特@JiarYoo ,求一波关注。?
欢迎关注个人我的微信订阅号,我将不按期分享开发方面的干货。