swift 中的 AnyObject 和 Any

Inlight發表於2017-12-17

誕生

swift 作為新起步的語言,必然拋不掉一些歷史遺留包袱。用過 Objective-C 的同學肯定知道有一種叫做 id 的型別。他可以表示任意類的例項,編譯器不會對其型別宣告的變數進行檢查。在用 swift 做 app 開發時,為了能適配 Cocoa 架構,AnyObject 就誕生了。它可以代表任意 class 型別(用來替代OC中的 id)。

區別

在 Swift 中編譯器會對 AnyObject 例項的方法呼叫做檢查,還會返回一個 Optional 的結果。

原理

public typealias AnyObject
// The protocol to which all class types implicitly conform.
複製程式碼

由定義就可以看出它就是一個介面,所有的 class 都隱式地實現了這個藉口。所以 AnyObject 只適用於 class 型別。但是 swift 中的基本型別都是 struct 型別,並不能用 AnyObject 來表示。所以官方又提出了一個更特殊的 Any 型別,它除了 class 以外還可以表示其他型別,可以說是任意型別(包括 struct,enum,func等)。

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let swiftArr = ["a", "b", "c"]
        let swiftStr = "hello world"
        
        var array = [AnyObject]()
        array.append(swiftArr)
        array.append(swiftStr)
    }
}
複製程式碼

這種寫法是會報錯的,String 不符合預期型別 AnyObject,並且系統提示了我們怎麼修改:

Argument type 'String' does not conform to expected type 'AnyObject' Insert ' as AnyObject'
複製程式碼

按提示修改後:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let swiftArr = ["a", "b", "c"]
        let swiftStr = "hello world"
        
        var array = [AnyObject]()
        array.append(swiftArr as AnyObject)
        array.append(swiftStr as AnyObject)
    }
}
複製程式碼

這裡我們顯示的將 swift 中的 String 和 Array 轉成了 AnyObject。實際上 array 裡面的元素已經變成了 NSString 和 NSArray 了。

swift 中的 AnyObject 和 Any
當然我們還有另外的方式解決此問題,用 Any。

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let swiftArr = ["a", "b", "c"]
        let swiftStr = "hello world"
        
        var array = [Any]()
        array.append(swiftArr)
        array.append(swiftStr)
    }
}
複製程式碼

可以看到結果全部是 swift 中的原生型別:

swift 中的 AnyObject 和 Any

注意

  • 只是用 swift 型別而不轉為 Cocoa 型別是會提升效能的,所以我們最好還是使用原生型別。
  • 在 OC 和 swift 混編的工程中使用 AnyObject 和 Any 是在所難免的,但我們要儘量避免使用這兩者,swift 中最好明確地指出確定的型別。
  • 如果我們的程式碼經常用到這兩者,意味著程式碼可能在結構和設計上存在問題。

相關文章