Attributes
Add information to declarations and types.
There are two kinds of attributes in Swift ---
those that apply to declarations and those that apply to types.
An attribute provides additional information about the declaration or type.
For example,
the discardableResult attribute on a function declaration indicates that,
although the function returns a value,
the compiler shouldn't generate a warning if the return value is unused.
You specify an attribute by writing the @ symbol followed by the attribute's name
and any arguments that the attribute accepts:
@<#attribute name#>
@<#attribute name#>(<#attribute arguments#>)
Some declaration attributes accept arguments that specify more information about the attribute and how it applies to a particular declaration. These attribute arguments are enclosed in parentheses, and their format is defined by the attribute they belong to.
Attached macros and property wrappers also use attribute syntax. For information about how macros expand, see doc:Expressions#Macro-Expansion-Expression. For information about property wrappers, see doc:Attributes#propertyWrapper.
Declaration Attributes
You can apply a declaration attribute to declarations only.
attached
Apply the attached attribute to a macro declaration.
The arguments to this attribute indicate the macro's role.
For a macro that has multiple roles,
apply the attached macro multiple times, once for each role.
The first argument to this attribute indicates the macro's role:
term Peer macros: Write
peeras the first argument to this attribute. The type that implements the macro conforms to thePeerMacroprotocol. These macros produce new declarations in the same scope as the declaration that the macro is attached to. For example, applying a peer macro to a method of a structure can define additional methods and properties on that structure.term Member macros: Write
memberas the first argument to this attribute. The type that implements the macro conforms to theMemberMacroprotocol. These macros produce new declarations that are members of the type or extension that the macro is attached to. For example, applying a member macro to a structure declaration can define additional methods and properties on that structure.term Member attribute: Write
memberAttributeas the first argument to this attribute. The type that implements the macro conforms to theMemberAttributeMacroprotocol. These macros add attributes to members of the type or extension that the macro is attached to.term Accessor macros: Write
accessoras the first argument to this attribute. The type that implements the macro conforms to theAccessorMacroprotocol. These macros add accessors to the stored property they're attached to, turning it into a computed property.term Extension macros: Write
extensionas the first argument to this attribute. The type that implements the macro conforms to theExtensionMacroprotocol. These macros can add protocol conformance, awhereclause, and new declarations that are members of the type the macro is attached to. If the macro adds protocol conformances, include theconformances:argument and specify those protocols. The conformance list contains protocol names, type aliases that refer to conformance list items, or protocol compositions of conformance list items. An extension macro on a nested type expands to an extension at the top level of that file. You can't write an extension macro on an extension, a type alias, or a type that's nested inside a function, or use an extension macro to add an extension that has a peer macro.
The peer and member macro roles require a names: argument,
listing the names of the symbols that the macro generates.
The accessor macro role requires a names: argument if the
macro generates a willSet or didSet property observer. An
accessor macro that generates property observers can't add
other accessors, because observers only apply to stored properties.
The extension macro role also requires a names: argument
if the macro adds declarations inside the extension.
When a macro declaration includes the names: argument,
the macro implementation must generate
only symbol with names that match that list.
That said,
a macro need not generate a symbol for every listed name.
The value for that argument is a list of one or more of the following:
named(<#name#>)where name is that fixed symbol name, for a name that's known in advance.overloadedfor a name that's the same as an existing symbol.prefixed(<#prefix#>)where prefix is prepended to the symbol name, for a name that starts with a fixed string.suffixed(<#suffix#>)where suffix is appended to the symbol name, for a name that ends with a fixed string.arbitraryfor a name that can't be determined until macro expansion.
As a special case,
you can write prefixed($)
for a macro that behaves similar to a property wrapper.
available
Apply this attribute to indicate a declaration's life cycle relative to certain Swift language versions or certain platforms and operating system versions.
The available attribute always appears
with a list of two or more comma-separated attribute arguments.
These arguments begin with one of the following platform or language names:
iOSiOSApplicationExtensionmacOSmacOSApplicationExtensionmacCatalystmacCatalystApplicationExtensionwatchOSwatchOSApplicationExtensiontvOStvOSApplicationExtensionvisionOSvisionOSApplicationExtensionswift
You can also use an asterisk (*) to indicate the
availability of the declaration on all of the platform names listed above.
An available attribute
that specifies availability using a Swift version number
can't use the asterisk.
The remaining arguments can appear in any order and specify additional information about the declaration's life cycle, including important milestones.
The
unavailableargument indicates that the declaration isn't available on the specified platform. This argument can't be used when specifying Swift version availability.The
introducedargument indicates the first version of the specified platform or language in which the declaration was introduced. It has the following form:introduced: <#version number#>The version number consists of one to three positive integers, separated by periods.
The
deprecatedargument indicates the first version of the specified platform or language in which the declaration was deprecated. It has the following form:deprecated: <#version number#>The optional version number consists of one to three positive integers, separated by periods. Omitting the version number indicates that the declaration is currently deprecated, without giving any information about when the deprecation occurred. If you omit the version number, omit the colon (
:) as well.The
obsoletedargument indicates the first version of the specified platform or language in which the declaration was obsoleted. When a declaration is obsoleted, it's removed from the specified platform or language and can no longer be used. It has the following form:obsoleted: <#version number#>The version number consists of one to three positive integers, separated by periods.
The
noasyncargument indicates that the declared symbol can't be used directly in an asynchronous context.Because Swift concurrency can resume on a different thread after a potential suspension point, using elements like thread-local storage, locks, mutexes, or semaphores across suspension points can lead to incorrect results.
To avoid this problem, add an
@available(*, noasync)attribute to the symbol's declaration:extension pthread_mutex_t { @available(*, noasync) mutating func lock() { pthread_mutex_lock(&self) } @available(*, noasync) mutating func unlock() { pthread_mutex_unlock(&self) } }This attribute raises a compile-time error when someone uses the symbol in an asynchronous context. You can also use the
messageargument to provide additional information about the symbol.@available(*, noasync, message: "Migrate locks to Swift concurrency.") mutating func lock() { pthread_mutex_lock(&self) }If you can guarantee that your code uses a potentially unsafe symbol in a safe manner, you can wrap it in a synchronous function and call that function from an asynchronous context.
// Provide a synchronous wrapper around methods with a noasync declaration. extension pthread_mutex_t { mutating func withLock(_ operation: () -> ()) { self.lock() operation() self.unlock() } } func downloadAndStore(key: Int, dataStore: MyKeyedStorage, dataLock: inout pthread_mutex_t) async { // Safely call the wrapper in an asynchronous context. dataLock.withLock { dataStore[key] = downloadContent() } }You can use the
noasyncargument on most declarations; however, you can't use it when declaring deinitializers. Swift must be able to call a class's deinitializers from any context, both synchronous and asynchronous.The
messageargument provides a textual message that the compiler displays when emitting a warning or error about the use of a declaration markeddeprecated,obsoleted, ornoasync. It has the following form:message: <#message#>The message consists of a string literal.
The
renamedargument provides a textual message that indicates the new name for a declaration that's been renamed. The compiler displays the new name when emitting an error about the use of a renamed declaration. It has the following form:renamed: <#new name#>The new name consists of a string literal.
You can apply the
availableattribute with therenamedandunavailablearguments to a type alias declaration, as shown below, to indicate that the name of a declaration changed between releases of a framework or library. This combination results in a compile-time error that the declaration has been renamed.// First release protocol MyProtocol { // protocol definition }// Subsequent release renames MyProtocol protocol MyRenamedProtocol { // protocol definition } @available(*, unavailable, renamed: "MyRenamedProtocol") typealias MyProtocol = MyRenamedProtocol
You can apply multiple available attributes on a single declaration
to specify the declaration's availability on different platforms
and different versions of Swift.
The declaration that the available attribute applies to
is ignored if the attribute specifies
a platform or language version that doesn't match the current target.
If you use multiple available attributes,
the effective availability is the combination of
the platform and Swift availabilities.
If an available attribute only specifies an introduced argument
in addition to a platform or language name argument,
you can use the following shorthand syntax instead:
@available(<#platform name#> <#version number#>, *)
@available(swift <#version number#>)
The shorthand syntax for available attributes
concisely expresses availability for multiple platforms.
Although the two forms are functionally equivalent,
the shorthand form is preferred whenever possible.
@available(iOS 10.0, macOS 10.12, *)
class MyClass {
// class definition
}
An available attribute
that specifies availability using a Swift version number
can't additionally specify a declaration's platform availability.
Instead, use separate available attributes to specify a Swift
version availability and one or more platform availabilities.
@available(swift 3.0.2)
@available(macOS 10.12, *)
struct MyStruct {
// struct definition
}
backDeployed
Apply this attribute to a function, method, subscript, or computed property to include a copy of the symbol's implementation in programs that call or access the symbol. You use this attribute to annotate symbols that ship as part of a platform, like the APIs that are included with an operating system. This attribute marks symbols that can be made available retroactively by including a copy of their implementation in programs that access them. Copying the implementation is also known as emitting into the client.
This attribute takes a before: argument,
specifying the first version of platforms that provide this symbol.
These platform versions have the same meaning
as the platform version you specify for the available attribute.
Unlike the available attribute,
the list can't contain an asterisk (*) to refer to all versions.
For example, consider the following code:
@available(iOS 16, *)
@backDeployed(before: iOS 17)
func someFunction() { /* ... */ }
In the example above,
the iOS SDK provides someFunction() starting in iOS 17.
In addition,
the SDK makes someFunction() available on iOS 16 using back deployment.
When compiling code that calls this function,
Swift inserts a layer of indirection that finds the function's implementation.
If the code is run using a version of the SDK that includes this function,
the SDK's implementation is used.
Otherwise, the copy included in the caller is used.
In the example above,
calling someFunction() uses the implementation from the SDK
when running on iOS 17 or later,
and when running on iOS 16
it uses the copy of someFunction() that's included in the caller.
Note: When the caller's minimum deployment target is the same as or greater than the first version of the SDK that includes the symbol, the compiler can optimize away the runtime check and call the SDK's implementation directly. In this case, if you access the back-deployed symbol directly, the compiler can also omit the copy of the symbol's implementation from the client.
Functions, methods, subscripts, and computed properties that meet the following criteria can be back deployed:
- The declaration is
publicor@usableFromInline. - For class instance methods and class type methods,
the method is marked
finaland isn't marked@objc. - The implementation satisfies the requirements for an inlinable function, described in doc:Attributes#inlinable.
discardableResult
Apply this attribute to a function or method declaration to suppress the compiler warning when the function or method that returns a value is called without using its result.
dynamicCallable
Apply this attribute to a class, structure, enumeration, or protocol
to treat instances of the type as callable functions.
The type must implement either a dynamicallyCall(withArguments:) method,
a dynamicallyCall(withKeywordArguments:) method,
or both.
You can call an instance of a dynamically callable type as if it's a function that takes any number of arguments.
@dynamicCallable
struct TelephoneExchange {
func dynamicallyCall(withArguments phoneNumber: [Int]) {
if phoneNumber == [4, 1, 1] {
print("Get Swift help on forums.swift.org")
} else {
print("Unrecognized number")
}
}
}
let dial = TelephoneExchange()
// Use a dynamic method call.
dial(4, 1, 1)
// Prints "Get Swift help on forums.swift.org".
dial(8, 6, 7, 5, 3, 0, 9)
// Prints "Unrecognized number".
// Call the underlying method directly.
dial.dynamicallyCall(withArguments: [4, 1, 1])
The declaration of the dynamicallyCall(withArguments:) method
must have a single parameter that conforms to the
ExpressibleByArrayLiteral
protocol --- like [Int] in the example above.
The return type can be any type.
You can include labels in a dynamic method call
if you implement the dynamicallyCall(withKeywordArguments:) method.
@dynamicCallable
struct Repeater {
func dynamicallyCall(withKeywordArguments pairs: KeyValuePairs<String, Int>) -> String {
return pairs
.map { label, count in
repeatElement(label, count: count).joined(separator: " ")
}
.joined(separator: "\n")
}
}
let repeatLabels = Repeater()
print(repeatLabels(a: 1, b: 2, c: 3, b: 2, a: 1))
// a
// b b
// c c c
// b b
// a
The declaration of the dynamicallyCall(withKeywordArguments:) method
must have a single parameter that conforms to the
ExpressibleByDictionaryLiteral
protocol,
and the return type can be any type.
The parameter's Key
must be
ExpressibleByStringLiteral.
The previous example uses KeyValuePairs
as the parameter type
so that callers can include duplicate parameter labels ---
a and b appear multiple times in the call to repeat.
If you implement both dynamicallyCall methods,
dynamicallyCall(withKeywordArguments:) is called
when the method call includes keyword arguments.
In all other cases, dynamicallyCall(withArguments:) is called.
You can only call a dynamically callable instance
with arguments and a return value that match the types you specify
in one of your dynamicallyCall method implementations.
The call in the following example doesn't compile because
there isn't an implementation of dynamicallyCall(withArguments:)
that takes KeyValuePairs<String, String>.
repeatLabels(a: "four") // Error
dynamicMemberLookup
Apply this attribute to a class, structure, enumeration, or protocol
to enable members to be looked up by name at runtime.
The type must implement a subscript(dynamicMember:) subscript.
In an explicit member expression,
if there isn't a corresponding declaration for the named member,
the expression is understood as a call to
the type's subscript(dynamicMember:) subscript,
passing information about the member as the argument.
The subscript can accept a parameter that's either a key path or a member name;
if you implement both subscripts,
the subscript that takes key path argument is used.
An implementation of subscript(dynamicMember:)
can accept key paths using an argument of type
KeyPath,
WritableKeyPath,
or ReferenceWritableKeyPath.
It can accept member names using an argument of a type that conforms to the
ExpressibleByStringLiteral protocol ---
in most cases, String.
The subscript's return type can be any type.
Dynamic member lookup by member name can be used to create a wrapper type around data that can't be type checked at compile time, such as when bridging data from other languages into Swift. For example:
@dynamicMemberLookup
struct DynamicStruct {
let dictionary = ["someDynamicMember": 325,
"someOtherMember": 787]
subscript(dynamicMember member: String) -> Int {
return dictionary[member] ?? 1054
}
}
let s = DynamicStruct()
// Use dynamic member lookup.
let dynamic = s.someDynamicMember
print(dynamic)
// Prints "325".
// Call the underlying subscript directly.
let equivalent = s[dynamicMember: "someDynamicMember"]
print(dynamic == equivalent)
// Prints "true".
Dynamic member lookup by key path can be used to implement a wrapper type in a way that supports compile-time type checking. For example:
struct Point { var x, y: Int }
@dynamicMemberLookup
struct PassthroughWrapper<Value> {
var value: Value
subscript<T>(dynamicMember member: KeyPath<Value, T>) -> T {
get { return value[keyPath: member] }
}
}
let point = Point(x: 381, y: 431)
let wrapper = PassthroughWrapper(value: point)
print(wrapper.x)
export
Apply this attribute to a function or method declaration to control how its definition is exported to client modules. Include one of the following arguments, indicating what aspect of the declaration to export:
The
interfaceargument specifies that only the interface is exported to clients, in the form of a callable symbol. The definition (function body) isn't available to clients for inlining, optimization, or any other purpose. Use this argument to hide the implementation from clients.The
implementationargument specifies that only the definition (function body) is exported to clients. There's no symbol for this function emitted into the binary, and clients are responsible for emitting a copy of the definition wherever it's required. Use this argument to introduce a new function or method without affecting the Application Binary Interface (ABI).
freestanding
Apply the freestanding attribute
to the declaration of a freestanding macro.
frozen
Apply this attribute to a structure or enumeration declaration to restrict the kinds of changes you can make to the type. This attribute is allowed only when compiling in library evolution mode. Future versions of the library can't change the declaration by adding, removing, or reordering an enumeration's cases or a structure's stored instance properties. These changes are allowed on nonfrozen types, but they break ABI compatibility for frozen types.
In library evolution mode, code that interacts with members of nonfrozen structures and enumerations is compiled in a way that allows it to continue working without recompiling even if a future version of the library adds, removes, or reorders some of that type's members. The compiler makes this possible using techniques like looking up information at runtime and adding a layer of indirection. Marking a structure or enumeration as frozen gives up this flexibility to gain performance: Future versions of the library can make only limited changes to the type, but the compiler can make additional optimizations in code that interacts with the type's members.
Frozen types,
the types of the stored properties of frozen structures,
and the associated values of frozen enumeration cases
must be public or marked with the usableFromInline attribute.
The properties of a frozen structure can't have property observers,
and expressions that provide the initial value for stored instance properties
must follow the same restrictions as inlinable functions,
as discussed in doc:Attributes#inlinable.
To enable library evolution mode on the command line,
pass the -enable-library-evolution option to the Swift compiler.
To enable it in Xcode,
set the "Build Libraries for Distribution" build setting
(BUILD_LIBRARY_FOR_DISTRIBUTION) to Yes,
as described in Xcode Help.
A switch statement over a frozen enumeration doesn't require a default case,
as discussed in doc:Statements#Switching-Over-Future-Enumeration-Cases.
Including a default or @unknown default case
when switching over a frozen enumeration
produces a warning because that code is never executed.
GKInspectable
Apply this attribute to expose a custom GameplayKit component property
to the SpriteKit editor UI.
Applying this attribute also implies the objc attribute.
globalActor
Apply this attribute to an actor, structure, enumeration, or final class.
The type must define a static property named shared,
which provides a shared instance of an actor.
A global actor generalizes the concept of actor isolation
to state that's spread out in several different places in code ---
such as multiple types, files, and modules ---
and makes it possible to safely access global variables from concurrent code.
The actor that the global actor provides
as the value of its shared property
serializes access to all this state.
You can also use a global actor to model constraints in concurrent code
like code that all needs to execute on the same thread.
Global actors implicitly conform to the GlobalActor protocol.
The main actor is a global actor provided by the standard library,
as discussed in doc:Concurrency#The-Main-Actor.
Most code can use the main actor instead of defining a new global actor.
inlinable
Apply this attribute to a function, method, computed property, subscript, convenience initializer, or deinitializer declaration to expose that declaration's implementation as part of the module's public interface. The compiler is allowed to replace calls to an inlinable symbol with a copy of the symbol's implementation at the call site.
Inlinable code
can interact with open and public symbols declared in any module,
and it can interact with internal symbols
declared in the same module
that are marked with the usableFromInline attribute.
Inlinable code can't interact with private or fileprivate symbols.
This attribute can't be applied
to declarations that are nested inside functions
or to fileprivate or private declarations.
Functions and closures that are defined inside an inlinable function
are implicitly inlinable,
even though they can't be marked with this attribute.
main
Apply this attribute to a structure, class, or enumeration declaration
to indicate that it contains the top-level entry point for program flow.
The type must provide a main type function
that doesn't take any arguments and returns Void.
For example:
@main
struct MyTopLevel {
static func main() {
// Top-level code goes here
}
}
Another way to describe the requirements of the main attribute
is that the type you write this attribute on
must satisfy the same requirements
as types that conform to the following hypothetical protocol:
protocol ProvidesMain {
static func main() throws
}
The Swift code you compile to make an executable can contain at most one top-level entry point, as discussed in doc:Declarations#Top-Level-Code.
nonobjc
Apply this attribute to a
method, property, subscript, or initializer declaration
to suppress an implicit objc attribute.
The nonobjc attribute tells the compiler
to make the declaration unavailable in Objective-C code,
even though it's possible to represent it in Objective-C.
Applying this attribute to an extension
has the same effect as
applying it to every member of that extension
that isn't explicitly marked with the objc attribute.
You use the nonobjc attribute to resolve circularity
for bridging methods in a class marked with the objc attribute,
and to allow overloading of methods and initializers
in a class marked with the objc attribute.
A method marked with the nonobjc attribute
can't override a method marked with the objc attribute.
However, a method marked with the objc attribute
can override a method marked with the nonobjc attribute.
Similarly, a method marked with the nonobjc attribute
can't satisfy a protocol requirement
for a method marked with the objc attribute.
NSApplicationMain
Deprecated: This attribute is deprecated; use the doc:Attributes#main attribute instead. In Swift 6, using this attribute produces a compile-time error.
Apply this attribute to a class
to indicate that it's the app delegate.
Using this attribute is equivalent to calling the
NSApplicationMain(_:_:) function.
If you don't use this attribute,
supply a main.swift file with code at the top level
that calls the NSApplicationMain(_:_:) function as follows:
import AppKit
NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)
The Swift code you compile to make an executable can contain at most one top-level entry point, as discussed in doc:Declarations#Top-Level-Code.
NSCopying
Apply this attribute to a stored variable property of a class.
This attribute causes the property's setter to be synthesized with a copy
of the property's value --- returned by the copyWithZone(_:) method --- instead of the
value of the property itself.
The type of the property must conform to the NSCopying protocol.
The NSCopying attribute behaves in a way similar to the Objective-C copy
property attribute.