原文地址: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 ,求一波關注。?
歡迎關注個人我的微信訂閱號,我將不按期分享開發方面的乾貨。