這里的教程為Swift官方教程中文版。

特性(Attributes)


1.0 翻譯:Hawstein 校對(duì):numbbbbb, stanzhai

2.0 翻譯+校對(duì):KYawn

2.1 翻譯:小鐵匠Linus

本頁(yè)內(nèi)容包括:

特性提供了有關(guān)聲明和類型的更多信息。在Swift中有兩種特性,分別用于修飾聲明和類型。

您可以通過(guò)以下方式指定一個(gè)特性:符號(hào)@后跟特性的名稱和特性接收的任何參數(shù):

@ 特性名

@ 特性名特性參數(shù)

有些聲明特性通過(guò)接收參數(shù)來(lái)指定特性的更多信息以及它是如何修飾某個(gè)特定的聲明的。這些特性的參數(shù)寫在圓括號(hào)內(nèi),它們的格式由它們所屬的特性來(lái)定義。

聲明特性

聲明特性只能應(yīng)用于聲明。

available

available 特性用于聲明時(shí),表示該聲明的生命周期與特定的平臺(tái)和操作系統(tǒng)版本有關(guān)。

available 特性經(jīng)常與參數(shù)列表一同出現(xiàn),該參數(shù)列表至少有兩個(gè)特性參數(shù),參數(shù)之間由逗號(hào)分隔。這些參數(shù)由以下這些平臺(tái)名字中的一個(gè)起頭:

  • iOS
  • iOSApplicationExtension
  • macOS
  • macOSApplicationExtension
  • watchOS
  • watchOSApplicationExtension
  • tvOS
  • tvOSApplicationExtension

當(dāng)然,你也可以用一個(gè)星號(hào)(*)來(lái)表示上面提到的所有平臺(tái)。 其余的參數(shù),可以按照任何順序出現(xiàn),并且可以添加關(guān)于聲明生命周期的附加信息,包括重要事件。

  • unavailable參數(shù)表示該聲明在指定的平臺(tái)上是無(wú)效的。
  • introduced 參數(shù)表示指定平臺(tái)從哪一版本開始引入該聲明。格式如下:

introduced=版本號(hào)

版本號(hào)由一個(gè)或多個(gè)正整數(shù)構(gòu)成,由句點(diǎn)分隔的。

  • deprecated參數(shù)表示指定平臺(tái)從哪一版本開始棄用該聲明。格式如下:

deprecated=版本號(hào)

可選的版本號(hào)由一個(gè)或多個(gè)正整數(shù)構(gòu)成,由句點(diǎn)分隔的。省略版本號(hào)表示該聲明目前已棄用,當(dāng)棄用出現(xiàn)時(shí)無(wú)需給出任何有關(guān)信息。如果你省略了版本號(hào),冒號(hào)(:)也可省略。

  • obsoleted 參數(shù)表示指定平臺(tái)從哪一版本開始廢棄該聲明。當(dāng)一個(gè)聲明被廢棄后,它就從平臺(tái)中移除,不能再被使用。格式如下:

obsoleted=版本號(hào)

版本號(hào)由一個(gè)或多個(gè)正整數(shù)構(gòu)成,由句點(diǎn)分隔的。

  • message 參數(shù)用來(lái)提供文本信息。當(dāng)使用被棄用或者被廢棄的聲明時(shí),編譯器會(huì)拋出警告或錯(cuò)誤信息。格式如下:

message=信息內(nèi)容

信息內(nèi)容由一個(gè)字符串構(gòu)成。

  • renamed 參數(shù)用來(lái)提供文本信息,用以表示被重命名的聲明的新名字。當(dāng)使用聲明的舊名字時(shí),編譯器會(huì)報(bào)錯(cuò)提示新名字。格式如下:

renamed=新名字

新名字由一個(gè)字符串構(gòu)成。

你可以將renamed 參數(shù)和 unavailable 參數(shù)以及類型別名聲明組合使用,以此向用戶表示某個(gè)聲明已經(jīng)被重命名。當(dāng)某個(gè)聲明的名字在一個(gè)框架或者庫(kù)的不同發(fā)布版本間發(fā)生變化時(shí),這會(huì)相當(dāng)有用。

// 首發(fā)版本
protocol MyProtocol {
// 這里是協(xié)議定義
}
// 后續(xù)版本重命名了 MyProtocol
protocol MyRenamedProtocol {
// 這里是協(xié)議定義
}
@available(*, unavailable, renamed:"MyRenamedProtocol")
typealias MyProtocol = MyRenamedProtocol

你可以在某個(gè)聲明上使用多個(gè) available 特性,以指定該聲明在不同平臺(tái)上的可用性。編譯器只有在當(dāng)前目標(biāo)平臺(tái)和 available 特性中指定的平臺(tái)匹配時(shí),才會(huì)使用 available 特性。

如果 available 特性除了平臺(tái)名稱參數(shù)外,只指定了一個(gè) introduced 參數(shù),那么可以使用以下簡(jiǎn)寫語(yǔ)法代替:

@available(平臺(tái)名稱 版本號(hào),*)

available 特性的簡(jiǎn)寫語(yǔ)法可以簡(jiǎn)明地表達(dá)出聲明在多個(gè)平臺(tái)上的可用性。盡管這兩種形式在功能上是相同的,但請(qǐng)盡可能地使用簡(jiǎn)寫語(yǔ)法形式。

@available(iOS 10.0, macOS 10.12, *)
class MyClass {
// 這里是類定義
}

discardableResult

該特性用于的函數(shù)或方法聲明,以抑制編譯器中 函數(shù)或方法的返回值被調(diào)而沒(méi)有使用其結(jié)果的警告。

GKInspectable

應(yīng)用此屬性,暴露一個(gè)自定義GameplayKit組件屬性給SpriteKit編輯器UI。

objc

該特性用于修飾任何可以在 Objective-C 中表示的聲明。比如,非嵌套類、協(xié)議、非泛型枚舉(僅限原始值為整型的枚舉)、類和協(xié)議中的屬性和方法(包括存取方法)、構(gòu)造器、析構(gòu)器以及下標(biāo)運(yùn)算符。objc 特性告訴編譯器這個(gè)聲明可以在 Objective-C 代碼中使用。

標(biāo)有 objc 特性的類必須繼承自 Objective-C 中定義的類。如果你將 objc 特性應(yīng)用于一個(gè)類或協(xié)議,它也會(huì)隱式地應(yīng)用于類或協(xié)議中兼容 Objective-C 的成員。對(duì)于標(biāo)記了 objc 特性的類,編譯器會(huì)隱式地為它的子類添加 objc 特性。標(biāo)記了 objc 特性的協(xié)議不能繼承沒(méi)有標(biāo)記 objc 的協(xié)議。

如果你將 objc 特性應(yīng)用于枚舉,每一個(gè)枚舉用例都會(huì)以枚舉名稱和用例名稱組合的方式暴露在 Objective-C 代碼中。例如,在 Planet 枚舉中有一個(gè)名為 Venus 的用例,該用例暴露在 Objective-C 代碼中時(shí)叫做 PlanetVenus。

objc 特性有一個(gè)可選的參數(shù),由標(biāo)識(shí)符構(gòu)成。當(dāng)你想把 objc 所修飾的實(shí)體以一個(gè)不同的名字暴露給 Objective-C 時(shí),你就可以使用這個(gè)特性參數(shù)。你可以使用這個(gè)參數(shù)來(lái)命名類、枚舉類型、枚舉用例、協(xié)議、方法、存取方法以及構(gòu)造器。下面的例子把 ExampleClass 中的 enabled 屬性的取值方法暴露給 Objective-C,名字是 isEnabled,而不是它原來(lái)的屬性名。

@objc
class ExampleClass: NSObject {
var enabled: Bool {
@objc(isEnabled) get {
// 返回適當(dāng)?shù)闹?}
}
}

nonobjc

該特性用于方法、屬性、下標(biāo)、或構(gòu)造器的聲明,這些聲明本可以在 Objective-C 代碼中使用,而使用 nonobjc 特性則告訴編譯器這個(gè)聲明不能在 Objective-C 代碼中使用。

可以使用 nonobjc 特性解決標(biāo)有 objc 的類中橋接方法的循環(huán)問(wèn)題,該特性還允許對(duì)標(biāo)有 objc 的類中的構(gòu)造器和方法進(jìn)行重載。

標(biāo)有 nonobjc 特性的方法不能重寫標(biāo)有 objc 特性的方法。然而,標(biāo)有 objc 特性的方法可以重寫標(biāo)有 nonobjc 特性的方法。同樣,標(biāo)有 nonobjc 特性的方法不能滿足標(biāo)有 @objc 特性的協(xié)議中的方法要求。

NSApplicationMain

在類上使用該特性表示該類是應(yīng)用程序委托類,使用該特性與調(diào)用 NSApplicationMain(_:_:) 函數(shù)并且把該類的名字作為委托類的名字傳遞給函數(shù)的效果相同。

如果你不想使用這個(gè)特性,可以提供一個(gè) main.swift 文件,并在代碼頂層調(diào)用NSApplicationMain(_:_:) 函數(shù),如下所示:

import AppKit
NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)

NSCopying

該特性用于修飾一個(gè)類的存儲(chǔ)型變量屬性。該特性將使屬性的設(shè)值方法使用傳入值的副本進(jìn)行賦值,這個(gè)值由傳入值的 copyWithZone(_:) 方法返回。該屬性的類型必需符合 NSCopying 協(xié)議。

NSCopying 特性的行為與 Objective-C 中的 copy 特性相似。

NSManaged

該特性用于修飾 NSManagedObject 子類中的實(shí)例方法或存儲(chǔ)型變量屬性,表明它們的實(shí)現(xiàn)由 Core Data 在運(yùn)行時(shí)基于相關(guān)實(shí)體描述動(dòng)態(tài)提供。對(duì)于標(biāo)記了 NSManaged 特性的屬性,Core Data 也會(huì)在運(yùn)行時(shí)為其提供存儲(chǔ)。應(yīng)用這個(gè)特性也意味著objc特性。

testable

在導(dǎo)入允許測(cè)試的編譯模塊時(shí),該特性用于修飾 import 聲明,這樣就能訪問(wèn)被導(dǎo)入模塊中的任何標(biāo)有 internal 訪問(wèn)級(jí)別修飾符的實(shí)體,猶如它們被標(biāo)記了 public 訪問(wèn)級(jí)別修飾符。測(cè)試也可以訪問(wèn)使用internal或者public訪問(wèn)級(jí)別修飾符標(biāo)記的類和類成員,就像它們是open訪問(wèn)修飾符聲明的。

UIApplicationMain

在類上使用該特性表示該類是應(yīng)用程序委托類,使用該特性與調(diào)用 UIApplicationMain函數(shù)并且把該類的名字作為委托類的名字傳遞給函數(shù)的效果相同。

如果你不想使用這個(gè)特性,可以提供一個(gè) main.swift 文件,并在代碼頂層調(diào)用 UIApplicationMain(_:_:_:) 函數(shù)。比如,如果你的應(yīng)用程序使用一個(gè)繼承于 UIApplication 的自定義子類作為主要類,你可以調(diào)用 UIApplicationMain(_:_:_:) 函數(shù)而不是使用該特性。

Interface Builder 使用的聲明特性

Interface Builder 特性是 Interface Builder 用來(lái)與 Xcode 同步的聲明特性。Swift 提供了以下的 Interface Builder 特性:IBAction,IBOutlet,IBDesignable,以及IBInspectable 。這些特性與 Objective-C 中對(duì)應(yīng)的特性在概念上是相同的。

IBOutletIBInspectable 用于修飾一個(gè)類的屬性聲明,IBAction 特性用于修飾一個(gè)類的方法聲明,IBDesignable 用于修飾類的聲明。

IBActionIBOutlet 特性都意味著objc特性。

類型特性

類型特性只能用于修飾類型。

autoclosure

這個(gè)特性通過(guò)把表達(dá)式自動(dòng)封裝成無(wú)參數(shù)的閉包來(lái)延遲表達(dá)式的計(jì)算。它可以修飾類型為返回表達(dá)式結(jié)果類型的無(wú)參數(shù)函數(shù)類型的函數(shù)參數(shù)。關(guān)于如何使用 autoclosure 特性的例子,請(qǐng)參閱 自動(dòng)閉包函數(shù)類型。

convention 該特性用于修飾函數(shù)類型,它指出了函數(shù)調(diào)用的約定。

convention 特性總是與下面的參數(shù)之一一起出現(xiàn)。

  • swift 參數(shù)用于表示一個(gè) Swift 函數(shù)引用。這是 Swift 中函數(shù)值的標(biāo)準(zhǔn)調(diào)用約定。

  • block 參數(shù)用于表示一個(gè) Objective-C 兼容的塊引用。函數(shù)值會(huì)作為一個(gè)塊對(duì)象的引用,塊是一種 id 兼容的 Objective-C 對(duì)象,其中嵌入了調(diào)用函數(shù)。調(diào)用函數(shù)使用 C 的調(diào)用約定。

  • c 參數(shù)用于表示一個(gè) C 函數(shù)引用。函數(shù)值沒(méi)有上下文,不具備捕獲功能,同樣使用 C 的調(diào)用約定。

使用 C 函數(shù)調(diào)用約定的函數(shù)也可用作使用 Objective-C 塊調(diào)用約定的函數(shù),同時(shí)使用 Objective-C 塊調(diào)用約定的函數(shù)也可用作使用 Swift 函數(shù)調(diào)用約定的函數(shù)。然而,只有非泛型的全局函數(shù)、局部函數(shù)以及未捕獲任何局部變量的閉包,才可以被用作使用 C 函數(shù)調(diào)用約定的函數(shù)。

escaping 在函數(shù)或者方法聲明上使用該特性,它表示參數(shù)將不會(huì)被存儲(chǔ)以供延遲執(zhí)行,這將確保參數(shù)不會(huì)超出函數(shù)調(diào)用的生命周期。在使用 escaping 聲明特性的函數(shù)類型中訪問(wèn)屬性和方法時(shí)不需要顯式地使用 self.。關(guān)于如何使用 escaping 特性的例子,請(qǐng)參閱 逃逸閉包

特性語(yǔ)法

特性 → @ 特性名 特性參數(shù)子句可選

特性名標(biāo)識(shí)符

特性參數(shù)子句 → ( 均衡令牌列表可選 )

特性列表特性 特性列表可選

均衡令牌列表均衡令牌 均衡令牌列表可選

均衡令牌 → ( 均衡令牌列表可選 )

均衡令牌 → [ 均衡令牌列表可選 ]

均衡令牌 → { 均衡令牌列表可選}

均衡令牌 → 任意標(biāo)識(shí)符,關(guān)鍵字,字面量或運(yùn)算符

均衡令牌 → 任意標(biāo)點(diǎn)除了 (,),[,],{,或 }

? 聲明 模式 ?
?