swift4.0 適配

原文地址:swift4.0 適配


一疯汁、前言

在我們的工程中處于swift和OC混編的狀態(tài)娩践,使用swift已經(jīng)有一年半的時間了三妈,隨著Xcode9的更新陪腌,swift3.2和swift4.0也隨之到來辱魁,swift3.2相較于Xcode8的swift3.1變動極小烟瞧,適配沒遇到問題,主要關(guān)注swift4.0的適配染簇。

二参滴、查看當(dāng)前工程的 swift 版本

三、使用 Xcode 將工程轉(zhuǎn)換到 swift4.0

1锻弓、環(huán)境

Xcode9.1

當(dāng)前swift版本 3.2

2砾赔、轉(zhuǎn)換步驟:

選中要轉(zhuǎn)換的target

Edit -> Convert -> To Current Swift Syntax

勾選需要轉(zhuǎn)換的target(pod引用不用勾選),Next

選擇轉(zhuǎn)換選項青灼,Next

這兩個選項是關(guān)于swift的@objc推斷特性的暴心,如果使用了swift4.0顯式的@objc屬性,能減少整體代碼的大小杂拨。此時我們選 Minimize Inference(recommend)专普,

關(guān)于兩個選項:

Minimize Inference(recommend)

根據(jù)靜態(tài)推斷,僅在需要的地方添加@objc屬性弹沽。使用此選項后檀夹,需要按照Completing a Swift 4 minimize inference migration來完成轉(zhuǎn)換。

Match Swift 3 Behavior

在編譯器隱式推斷的任何地方向代碼添加一個@objc屬性策橘。這個選項不會改變你的二進(jìn)制文件的大小炸渡,因為被Swift 3隱式推斷在所有的地方都添加了顯式的@objc屬性。

預(yù)覽轉(zhuǎn)換代碼丽已,沒問題蚌堵,Save。

3促脉、修改錯誤

完成上述5步之后辰斋,看一下swift版本,已經(jīng)是4.0了:

至此打完收工瘸味,適配結(jié)束。然而并沒有够挂,當(dāng)你運(yùn)行的時候會看到這個:

是否欲哭無淚旁仿,居然這么多錯誤,不用怕孽糖,其實要改動的地方并不多枯冈,有些都是重復(fù)的,可以直接全局替換就行办悟。

舉個栗子:

- class dynamic func

// 轉(zhuǎn)換前
class dynamic func bookMoneyToUpController() -> MPBookMoneyToUpController {
??? let vc = MPBookMoneyToUpController.init(nibName: "MPBookMoneyToUpController", bundle: Bundle.main)
??? return vc
}

// 轉(zhuǎn)換后
class @objc dynamic func bookMoneyToUpController() -> MPBookMoneyToUpController {
??? let vc = MPBookMoneyToUpController.init(nibName: "MPBookMoneyToUpController", bundle: Bundle.main)
??? return vc
}

// 問題 @objc 修飾符需要前置
// 修改成下面即可
@objc class dynamic func bookMoneyToUpController() -> MPBookMoneyToUpController {
??? let vc = MPBookMoneyToUpController.init(nibName: "MPBookMoneyToUpController", bundle: Bundle.main)
??? return vc
}

// 全局替換即可
class @objc dynamic func? -> @objc class dynamic func

上面使用dynamic修飾符是由于以前使用JSPatch來做hotfix尘奏,需要用到原來OC的運(yùn)行時特性。

四病蛉、@objc

swift4.0最大的特性之一就是@objc修飾符的變化了炫加,它主要處理OC和swift混編時一些方法的調(diào)用以及屬性獲取問題瑰煎,swift4.0將在swift3.x中一些隱式類型推斷的特性去除以后,需要我們來手動管理@objc修飾符俗孝。

在上文中使用Xcode轉(zhuǎn)換swift4.0時我們勾選了Minimize Inference選項酒甸,那么我們就需要手動處理相關(guān)的@objc修飾符,來保證OC和swift代碼能正常相互調(diào)用赋铝。

1插勤、@objc修飾符手動處理步驟

使用“最小化”轉(zhuǎn)換代碼后,需要處理構(gòu)建和運(yùn)行時的問題革骨,在完成初始的swift4.0轉(zhuǎn)換后农尖,需要按照下面步驟來處理其它問題。

1. 運(yùn)行你的工程

2. 修復(fù)編譯器提示需要添加@objc的地方

3. 測試你的代碼良哲,并修復(fù)編譯器提示使用了不推薦的隱式@objc引用的警告卤橄。直到?jīng)]有警告發(fā)生。

打開工程的build settings.

將Swift 3 @objc inference設(shè)置為Default.

2臂外、@objc修飾符需要處理的問題

編譯警告

swift 中編譯的警告

#selector參數(shù)指定的實例方法必須使用@objc修飾窟扑,因為swift4中棄用了@objc屬性推斷。

// 下面的代碼會有警告
class MyClass : NSObject {
??? func foo() {
??? }
???
??? func bar() {
??????? self.perform(#selector(MyClass.foo)
??? }
}
warning: argument of ‘#selector’ refers to instance method ‘foo’ in ‘MyClass’ that depends

Objective-C 編譯時警告

在OC中調(diào)用的swift方法漏健,在swift中需要追加@objc修飾嚎货,swift4廢棄了該類型推斷。

// 下面的代碼會有警告
@implementation MyClass (ObjCMethods)
- (void)other {
??? [self foo];
}
@end
warning: Swift method MyClass.foo uses @objc inference deprecated in Swift 4; add @objc to provide an Objective-C entrypoint

修復(fù)編譯時警告

// 通過追加 @objc 來消除警告
class MyClass : NSObject {
??? @objc func foo() {
??? }
???
??? func bar() {
??????? self.perform(#selector(MyClass.foo)
??? }
}


查看所有需要添加@objc的編譯警告

直接選中定位到相應(yīng)位置蔫浆,追加@objc修飾即可殖属。

運(yùn)行時警告

運(yùn)行時警告會打印在控制臺:

***Swift runtime:
ClassName.swift:lineInFile:columnInLine:
entrypoint -[ClassName methodName] generated by implicit @objc inference is deprecated and will be removed in Swift 4;
add explicit @objc to the declaration to emit the Objective-C entrypoint in Swift 4 and suppress this message

在Xcode9.1中讯蒲,運(yùn)行時警告在這里也能看到:

想要修復(fù)運(yùn)行時警告固耘,需要添加@objc修飾符到對應(yīng)的方法或者符號蜜另。

運(yùn)行時警告的常見原因:

在OC中使用SEL

在swift中使用了perform methods

在OC中使用了performSelector methods

使用了@IBOutlet或者@IBAction

class MyClass : NSObject {
??? func foo() {
??? }
???
??? func bar() {
??????? let selectorName = "foo"
??????? self.perform(Selector(selectorName)
??? }
}
***Swift runtime: MyClass.swift:7:7: entrypoint -[MyClass foo] generated by implicit @objc inference is deprecated and will be removed in Swift 4; add explicit @objc to the declaration to emit the Objective-C entrypoint in Swift 4 and suppress this message

五吸耿、swift4.0其它部分特性

1尘应、NSAttributedStringKey

NSAttributedString的初始化方法變化:

// swift3.x
public init(string str: String, attributes attrs: [AnyHashable : Any]? = nil)

// swift4.0
public init(string str: String, attributes attrs: [NSAttributedStringKey : Any]? = nil)

示例:

// 轉(zhuǎn)換前
let attributes = [NSForegroundColorAttributeName: RGB(128, g: 134, b: 146),
????????????????? NSParagraphStyleAttributeName: paragraph,
????????????????? NSFontAttributeName: UIFont.systemFont(ofSize: 14)] as [String : Any]
var tipAttrText = NSAttributedString.init(string: tipText, attributes: attributes)

// 轉(zhuǎn)換后
let attributes = [NSAttributedStringKey.foregroundColor.rawValue: RGB(128, g: 134, b: 146),
????????????????? NSAttributedStringKey.paragraphStyle: paragraph,
????????????????? NSAttributedStringKey.font: UIFont.systemFont(ofSize: 14)] as! [String : Any]
var tipAttrText = NSAttributedString(string: tipText, attributes: attributes)

// tipAttrText 初始化報錯提示
Cannot convert value of type '[String : Any]' to expected argument type '[NSAttributedStringKey : Any]?'

// 修改
NSAttributedStringKey.foregroundColor.rawValue -> NSAttributedStringKey.foregroundColor
去掉 as! [String : Any]

2棒动、String

String的characters屬性被廢棄了

let string = "abc" var count = string.characters.count // 第二行報錯 'characters' is deprecated: Please use String or Substring directly // 對應(yīng)新方法 count = string.count

String的addingPercentEscapes方法被廢棄了

// swift3.x
var url = @"http://www.example.com?username=姓名"
url = url.addingPercentEscapes(using: String.Encoding.utf8)!

// 報錯
'addingPercentEscapes(using:)' is unavailable: Use addingPercentEncoding(withAllowedCharacters:) instead, which always uses the recommended UTF-8 encoding, and which encodes for a specific URL component or subcomponent since each URL component or subcomponent has different rules for what characters are valid.

// 修改
uri = uri.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!

substring(to:)被廢棄了

let index = tagText.index(tagText.startIndex, offsetBy: MPMultipleStyleListItemTagMaxLength)

// 警告:'substring(to:)' is deprecated: Please use String slicing subscript with a 'partial range upto' operator.
let b = tagText.substring(to: index)

// 新 API
// 注意:a 的類型是 Substring婚脱,不是 String
let a = tagText.prefix(upTo: index)

3雹仿、initialize 廢棄

// swift3.x
override class func initialize() {
??? // some code
}

// 報錯
Method 'initialize()' defines Objective-C class method 'initialize', which is not permitted by Swift

Swift3.x 繼續(xù) Method Swizzling這篇文章里面介紹了一種解決思路嘱吗。

4玄组、swift3使用#selector指定的方法,只有當(dāng)方法權(quán)限為private時需要加@objc修飾符谒麦,swift4.0都要加@objc修飾符

// 示例代碼

func startMonitor() {

NotificationCenter.default.addObserver(self, selector: #selector(self.refreshUserLoginStatus), name: NSNotification.Name.XSLUserLogin, object: nil)

}

func refreshUserLoginStatus() {

// some code

}

// 第二行警告

Argument of '#selector' refers to instance method 'refreshUserLoginStatus()' in 'MPUnreadMessageCountManager' that depends on '@objc' inference deprecated in Swift 4

// 追加 private

func startMonitor() {

NotificationCenter.default.addObserver(self, selector: #selector(self.refreshUserLoginStatus), name: NSNotification.Name.XSLUserLogin, object: nil)

}

private func refreshUserLoginStatus() {

// some code

}

// 第二行報錯

Argument of '#selector' refers to instance method 'refreshUserLoginStatus()' that is not exposed to Objective-C

swift4.0不再允許重載extension中的方法(包括instance俄讹、static、class方法)

// 示例代碼
class TestSuperClass: NSObject {
}
extension TestSuperClass {
??? func test() {
??????? // some code
??? }
}
class TestClass: TestSuperClass {
??? // 報錯:Declarations from extensions cannot be overridden yet
??? override func test() {
??????? // some code
??? }
}

六绕德、pod引用

添加以下內(nèi)容到Podfile患膛。

post_install do |installer|
installer.pods_project.targets.each do |target|
if ['WTCarouselFlowLayout', 'XSLRevenue', 'OHHTTPStubs/Swift'].include? target.name
target.build_configurations.each do |config|
config.build_settings['SWIFT_VERSION'] = '3.2'
end
end
end
end

七、踩坑

UITableViewDelegate協(xié)議方法名變更耻蛇,沒有錯誤提示:

// swift3.x
func tableView(_ tableView: UITableView, heightForRowAtIndexPath indexPath: IndexPath) -> CGFloat

// swift4.0
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末踪蹬,一起剝皮案震驚了整個濱河市胞此,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌延曙,老刑警劉巖豌鹤,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異枝缔,居然都是意外死亡布疙,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進(jìn)店門愿卸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來灵临,“玉大人,你說我怎么就攤上這事趴荸∪甯龋” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵发钝,是天一觀的道長顿涣。 經(jīng)常有香客問我,道長酝豪,這世上最難降的妖魔是什么涛碑? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮孵淘,結(jié)果婚禮上蒲障,老公的妹妹穿的比我還像新娘。我一直安慰自己瘫证,他們只是感情好揉阎,可當(dāng)我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著背捌,像睡著了一般毙籽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上载萌,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天惧财,我揣著相機(jī)與錄音,去河邊找鬼扭仁。 笑死,一個胖子當(dāng)著我的面吹牛厅翔,可吹牛的內(nèi)容都是我干的乖坠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼刀闷,長吁一口氣:“原來是場噩夢啊……” “哼熊泵!你這毒婦竟也來了仰迁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤顽分,失蹤者是張志新(化名)和其女友劉穎徐许,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卒蘸,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡雌隅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了缸沃。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恰起。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖趾牧,靈堂內(nèi)的尸體忽然破棺而出检盼,到底是詐尸還是另有隱情,我是刑警寧澤翘单,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布吨枉,位于F島的核電站,受9級特大地震影響哄芜,放射性物質(zhì)發(fā)生泄漏貌亭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一忠烛、第九天 我趴在偏房一處隱蔽的房頂上張望属提。 院中可真熱鬧,春花似錦美尸、人聲如沸冤议。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽恕酸。三九已至,卻和暖如春胯陋,著一層夾襖步出監(jiān)牢的瞬間蕊温,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工遏乔, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留义矛,地道東北人。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓盟萨,卻偏偏與公主長得像凉翻,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子捻激,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 一制轰、前言 在我們的工程中處于swift和OC混編的狀態(tài)前计,使用swift已經(jīng)有一年半的時間了,隨著Xcode9的更新...
    wentianen閱讀 2,712評論 0 4
  • 1垃杖、隨機(jī)數(shù) 不需要隨機(jī)數(shù)種子 arc4random()%N + begin:產(chǎn)生begin~begin+N的隨機(jī)數(shù)...
    我是小胡胡123閱讀 4,161評論 0 2
  • iOS開發(fā)中男杈,我們需要根據(jù)用戶需要去適配各種各樣的版本,特別是蘋果爸爸的每一次新版本發(fā)布调俘,作為開發(fā)者的我們永遠(yuǎn)是最...
    青蘋果園閱讀 7,570評論 2 12
  • 只為個人記錄下來看看 swift4.0 適配 原文地址:http://blog.csdn.net/andanlan...
    擁抱月亮的大星星閱讀 374評論 0 1
  • 老教授要帶領(lǐng)我們參觀圖書館伶棒。因為白天人太多,所以選在晚上過去脉漏。 我們大約是一個班的人數(shù)苞冯,由教授和班長領(lǐng)路。班長好像...
    愿河閱讀 247評論 0 1