無標(biāo)題文章

只為個人記錄下來看看

swift4.0 適配

原文地址:
http://blog.csdn.net/andanlan/article/details/78491599?locationNum=1&fps=1

<a name="t0" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>一汤纸、前言

在我們的工程中處于swiftOC混編的狀態(tài),使用swift已經(jīng)有一年半的時間了,隨著Xcode9的更新垃僚,swift3.2swift4.0也隨之到來,swift3.2相較于Xcode8swift3.1變動極小沸手,適配沒遇到問題针炉,主要關(guān)注swift4.0的適配。

<a name="t1" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>二蔬墩、查看當(dāng)前工程的 swift 版本

image.png

<a name="t2" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>三、使用 Xcode 將工程轉(zhuǎn)換到 swift4.0

<a name="t3" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>1耗拓、環(huán)境

  • Xcode9.1

  • 當(dāng)前

    swift

    版本 3.2

<a name="t4" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>2拇颅、轉(zhuǎn)換步驟:

  1. 選中要轉(zhuǎn)換的

    target

  2. Edit -> Convert -> To Current Swift Syntax

    image.png
  3. 勾選需要轉(zhuǎn)換的

    target

    pod

    引用不用勾選),Next

    image.png
  4. 選擇轉(zhuǎn)換選項(xiàng)乔询,Next

    這兩個選項(xiàng)是關(guān)于

    swift

    @objc

    推斷特性的樟插,如果使用了

    swift4.0

    顯式的

    @objc

    屬性,能減少整體代碼的大小竿刁。此時我們選 Minimize Inference(recommend)黄锤,

    image.png

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

    • Minimize Inference(recommend)

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

    • Match Swift 3 Behavior

      在編譯器隱式推斷的任何地方向代碼添加一個@objc屬性负甸。這個選項(xiàng)不會改變你的二進(jìn)制文件的大小流强,因?yàn)楸籗wift 3隱式推斷在所有的地方都添加了顯式的@objc屬性。

  5. 預(yù)覽轉(zhuǎn)換代碼呻待,沒問題打月,Save。

<a name="t5" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>3蚕捉、修改錯誤

完成上述5步之后奏篙,看一下

swift

版本,已經(jīng)是4.0了:

image.png

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

image.png

是否欲哭無淚千绪,居然這么多錯誤充易,不用怕,其實(shí)要改動的地方并不多荸型,有些都是重復(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
image.png

上面使用

dynamic

修飾符是由于以前使用

JSPatch

來做

hotfix,需要用到原來OC的運(yùn)行時特性稿静。

<a name="t6" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>四梭冠、@objc

swift4.0

最大的特性之一就是

@objc

修飾符的變化了,它主要處理

OC

swift

混編時一些方法的調(diào)用以及屬性獲取問題改备,swift4.0

將在

swift3.x

中一些隱式類型推斷的特性去除以后控漠,需要我們來手動管理

@objc

修飾符。

在上文中使用

Xcode

轉(zhuǎn)換

swift4.0

時我們勾選了

Minimize Inference

選項(xiàng)悬钳,那么我們就需要手動處理相關(guān)的

@objc

修飾符盐捷,來保證

OC

swift

代碼能正常相互調(diào)用。

<a name="t7" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>1默勾、@objc

修飾符手動處理步驟

使用“最小化”轉(zhuǎn)換代碼后碉渡,需要處理構(gòu)建和運(yùn)行時的問題,在完成初始的

swift4.0

轉(zhuǎn)換后母剥,需要按照下面步驟來處理其它問題滞诺。

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

2. 修復(fù)編譯器提示需要添加

@objc

的地方

3. 測試你的代碼,并修復(fù)編譯器提示使用了不推薦的隱式

@objc

引用的警告环疼。直到?jīng)]有警告發(fā)生习霹。

  1. 打開工程的

    build settings.

  2. Swift 3 @objc inference

    設(shè)置為

    Default.

<a name="t8" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>2、@objc

修飾符需要處理的問題

  1. 編譯警告

    • swift 中編譯的警告

      #selector

      參數(shù)指定的實(shí)例方法必須使用

      @objc

      修飾炫隶,因?yàn)?code>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 on ‘@objc’ attribute inference deprecated in Swift 4
  • 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

    的編譯警告

    image.png

    直接選中定位到相應(yīng)位置,追加

    @objc

    修飾即可望门。

    1. 運(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)行時警告在這里也能看到:

image.png

想要修復(fù)運(yùn)行時警告锰霜,需要添加

@objc

修飾符到對應(yīng)的方法或者符號筹误。

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

    • OC

      中使用

      SEL

    • swift

      中使用了

      perform methods

    • OC

      中使用了

      performSelector methods

    • 使用了

      @IBOutlet

      或者

      @IBAction

// 下面 swift 代碼會產(chǎn)生運(yùn)行時警告
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

<a name="t9" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>五、swift4.0

其它部分特性

<a name="t10" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>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 初始化報(bào)錯提示
Cannot convert value of type '[String : Any]' to expected argument type '[NSAttributedStringKey : Any]?'

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

<a name="t11" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>2厨剪、String

  • String

    characters

    屬性被廢棄了

let string = "abc"
var count = string.characters.count

// 第二行報(bào)錯
'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)!

// 報(bào)錯
'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)

<a name="t12" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>3友存、initialize 廢棄

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

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

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

<a name="t13" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>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
}

// 第二行報(bào)錯
Argument of '#selector' refers to instance method 'refreshUserLoginStatus()' that is not exposed to Objective-C
  • swift4.0

    不再允許重載

    extension

    中的方法(包括instancestaticclass方法)

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

<a name="t14" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>六勇皇、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

<a name="t15" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: 400; outline: 0px;"></a>七、踩坑

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,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捕虽,死亡現(xiàn)場離奇詭異慨丐,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)薯鳍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進(jìn)店門咖气,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人挖滤,你說我怎么就攤上這事崩溪。” “怎么了斩松?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵伶唯,是天一觀的道長。 經(jīng)常有香客問我惧盹,道長乳幸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任钧椰,我火速辦了婚禮粹断,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嫡霞。我一直安慰自己瓶埋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布诊沪。 她就那樣靜靜地躺著养筒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪端姚。 梳的紋絲不亂的頭發(fā)上晕粪,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天,我揣著相機(jī)與錄音渐裸,去河邊找鬼巫湘。 笑死装悲,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的剩膘。 我是一名探鬼主播衅斩,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼怠褐!你這毒婦竟也來了畏梆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤奈懒,失蹤者是張志新(化名)和其女友劉穎奠涌,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體磷杏,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡溜畅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了极祸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慈格。...
    茶點(diǎn)故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖遥金,靈堂內(nèi)的尸體忽然破棺而出浴捆,到底是詐尸還是另有隱情,我是刑警寧澤稿械,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布选泻,位于F島的核電站,受9級特大地震影響美莫,放射性物質(zhì)發(fā)生泄漏页眯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一厢呵、第九天 我趴在偏房一處隱蔽的房頂上張望窝撵。 院中可真熱鬧,春花似錦襟铭、人聲如沸忿族。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至错英,卻和暖如春入撒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背椭岩。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工茅逮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留璃赡,地道東北人。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓献雅,卻偏偏與公主長得像碉考,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子挺身,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評論 2 354

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