@available 和 #available 的区别

657 阅读3分钟

这里每天分享一个 iOS 的新知识,快来关注我吧

前言

你可能会在代码中看到 #available@available 两个关键字,它们都用作 API 可用性相关的功能,但是它们之间有什么区别呢?今天就来讲讲这两个关键字。

#available 和 #unavailable

#available 关键字主要是用作 ifwhileguard 这几个条件语句的,可以在运行时来查询某个 API 的可用性。

先看下定义:

#available(platform version , platform version ..., *)

platform 参数支持使用 iOSmacOSwatchOStvOS 作为平台名称,然后一个空格带上相应的版本号,然后最后有个 *,代表在其他任何平台上。

比如某个 API 在 iOS 15 及以上才能使用,我们的 App 最低兼容 iOS 12 以上,那么在用到这个 API 的时候就需要用这个关键字来做分别的实现:

if #available(iOS 15, *) {
    // 使用 iOS 15 可用的 API
} else {
    // 使用 iOS 15 以下的 API 实现
}

或者用 guard 实现:

guard #available(iOS 15, *) else {
    // 使用 iOS 15 以下的 API 实现
    return
}

// 使用 iOS 15 可用的 API

需要注意的是当有多个 #available 条件时,不能使用 && 和 || 等逻辑运算符,但是可以用逗号,比如判断在 iOS 15 或 macOS 13 以上可用:

if #available(iOS 15.0, *) || #available(macOS 13.0, *) {
    // 在 iOS 15 和 macOS 13 以上可用
}

在 swift 5.6 中,还引入了取反的操作,即:#unavailable,代表 #available 否定条件的语法糖。但是 * 参数是隐式的,不需要写:

if #unavailable(iOS 15) {
    // 使用 iOS 15 以下的 API 实现
}

@available

@available 是一个声明属性,可以将其应用在类或方法声明上,还可以指定这些类或方法支持的平台。

看下声明:

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

platform 是平台,支持 iOSmacCatalystmacOS / OSXtvOSwatchOS,或任何附加 ApplicationExtension 的平台(例如 macOSApplicationExtension)。然后一个空格后面加上版本,最后的星号 * 代表其他平台都可用:

比如 MyClass 在 iOS 15 以上可用:

@available(iOS 15, *)
class MyClass {
}

多个平台限制可以用逗号分隔:

@available(macOS 10.15, iOS 15, watchOS 6, tvOS 13, *)
class MyClass {
}

MyClass 这个类的声明上面加了 @available 意味着这个类只能在 macOS 10.15, iOS 15, watchOS 6, tvOS 13 以上使用。

@available 作用在方法上时,还可以标记这个方法的引入版本、过期版本、废弃版本和代替方法等信息:

@available(iOS 15, *)
class Person {
    @available(iOS,
               introduced: 15,
               deprecated: 16,
               obsoleted: 17,
               renamed: "newRun",
               message: "这个方法在 iOS 15 引入,在 iOS 16 过期,在 iOS 17 废弃,请尽快替换新方法 newRun")
    func run() { }
}

举个例子

假如我们有个类叫 PersonPerson 中有个方法 run,可以这样声明:

class Person {
    func run() { }
}

在 iOS 17 发布之后,苹果给了 run 方法实现的新 API,这时候为了使用新的 API 实现 run 方法,我可能会起一个新的方法 newRun,但是这个方法只能在 iOS 17 以上使用,所以就必须标记 @available(iOS 17, *)

class Person {
    @available(iOS 17, *)
    func newRun() { }
    
    func run() { }
}

那么当使用 Person 的人用到 newRun 方法的时候,如果是在 iOS 17 以下,就会报错:'newRun()' is only available in iOS 17 or newer,这这时候就需要用 @available 先做版本判断:

let person = Person()

if #available(iOS 17, *) {
    person.newRun()
} else {
    person.run()
}

点击下方公众号卡片,关注我,每天分享一个关于 iOS 的新知识

本文同步自微信公众号 “iOS新知”,每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!