寫更好的 Swift 程式碼:@available 與呼叫方進行溝通

語言: CN / TW / HK

保持程式碼不變很難,因為需求不斷在變化,系統、框架不斷在更新。那麼專案實踐中,往往會廢棄掉一些類或方法。如果是自己獨立維護程式碼,且不需要將程式碼給他人使用,廢棄 api 對你來說是非常簡單的,直接改動原始碼即可。但是對於多人合作的專案,特別是開源的庫,廢棄一個公開的 api 不是簡單的改動下程式碼就可以,因為你的改動將會影響使用你這個庫的所有程式碼。公開的api 的更新換代,就相當於你改動了和別人約定的契約一樣,這也側面反映了作者的專業水平。

那麼如果要廢棄一個 api,在 Swift 中我們該如何做?

小案例

Swift 提供了 @available 註解。可以簡單地將其附加到特定方法甚至整個類:

swift @available(*, deprecated) func oldMethod(value: Int) { print(value) }

這會就會出現以下警告:

-w394

如果我們要給廢棄的api,新增更多的廢棄資訊,我們可以這樣:

swift @available(*, deprecated, message: "不要再使用該方法了") func oldMethod(value: Int) { print(value) }

message 設定為 不要再使用該方法了,提示效果如下:

-w639

通常,廢棄了一個 Api,如果能提示呼叫方可以使用的新Api是什麼,那就非常完美了。如需要將舊的Api改名,就可以這麼做:

```swift @available(*, deprecated, renamed: "newMethod(number:)", message: "不要再使用該方法了") func oldMethod(value: Int) { print(value) }

func newMethod(number: Int) { print("值為:(number)") } ```

新增 renamed 後,我們的舊方法呼叫:

-w992

這種警告是可以展開的:

-w981

可以點選 Fix 按鈕,程式碼將自動替換為新的 API。

@available 歸類

@available 有這麼幾種宣告:

約束平臺和版本

swift @available(platform version , platform version ..., *)

舉例:

swift @available(iOS 14, *) class AppIntro { }

在呼叫的時候,我們需要通過 #available

swift if #available(iOS 14, *) { let appIntro = AppIntro() } else { // .. 14以下的版本呼叫 }

當然我們也可以指定多個平臺:

swift @available(iOS 14, macOS 11.0, *) class AppIntro { }

約束swift版本

swift @available(swift version)

比如需要 Swift 5.5 或更高版本才能使用 oldMethod

swift @available(swift 5.5) func oldMethod(value: Int) { print(value) }

約束指定平臺的 introduced, deprecated, obsoleted 和 unavailable

```swift // With introduced, deprecated, and/or obsoleted @available(platform | * , introduced: version , deprecated: version , obsoleted: version , renamed: "..." , message: "...")

// With unavailable @available(platform | *, unavailable , renamed: "..." , message: "...") ```

  • platform:平臺名稱
  • introduced:開始引進的版本號
  • deprecated:從指定平臺開始過期的版本
  • obsoleted:從指定平臺開始廢棄的版本(注意棄用的區別,deprecated 是還可以繼續使用,只不過是不推薦了,obsoleted 是呼叫就會編譯錯誤)
  • message:給出一些附加資訊
  • renamed:重新命名後的新名稱
  • unavailable:指定平臺上是無效的

這些引數可以相互組合使用。下面列舉幾個常用案例:

swift @available(iOS 13, *) @available(tvOS, unavailable) @available(macCatalyst, unavailable) func handleShakeGesture() { … }

總結

正確的使用@available註解可以增強你和你的API使用者之間的溝通,新舊API替換體驗會變得友好很多。

參考