Swift Public Attributes
Attributes provide additional information about the declarative type. There are two types of attributes, those that apply to declarations and those that apply to types. You specify an attribute by writing the @
symbol followed by the attribute’s name and any arguments that the attribute accepts:
1 2 |
@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 and these attribute arguments are enclosed in parentheses, and their format is defined by the attribute they belong to.
Below is the list of available attributes:
Declaration Attributes
Declaration Attributes Used by Interface Builder
Interface Builder attributes are declaration attributes used by Interface Builder to synchronize with Xcode. Swift provides the following Interface Builder attributes: IBAction
, IBSegueAction
, IBOutlet
, IBDesignable
, and IBInspectable
. These attributes are conceptually the same as their Objective-C counterparts.
You apply the IBOutlet
and IBInspectable
attributes to property declarations of a class. You apply the IBAction
and IBSegueAction
attribute to method declarations of a class and the IBDesignable
attribute to class declarations.
Applying the IBAction
, IBSegueAction
, IBOutlet
, IBDesignable
, or IBInspectable
attribute also implies the objc
attribute.
@UIApplicationMain
, @NSApplicationMain
Apply this attribute to a class to indicate that it’s the application delegate. Using this attribute is equivalent to calling the UIApplicationMain
function and passing this class’s name as the name of the delegate class.
@propertyWrapper
Apply this attribute to a class, structure, or enumeration declaration to use that type as a property wrapper. When you apply this attribute to a type, you create a custom attribute with the same name as the type. Apply that new attribute to a property of a class, structure, or enumeration to wrap access to the property through an instance of the wrapper type. Local and global variables can’t use property wrappers.
The wrapper must define a wrappedValue
instance property. The wrapped value of the property is the value that the getter and setter for this property expose. In most cases, wrappedValue
is a computed value, but it can be a stored value instead. The wrapper is responsible for defining and managing any underlying storage needed by its wrapped value. The compiler synthesizes storage for the instance of the wrapper type by prefixing the name of the wrapped property with an underscore (_
)—for example, the wrapper for someProperty
is stored as _someProperty
. The synthesized storage for the wrapper has an access control level of private
.
A property that has a property wrapper can include willSet
and didSet
blocks, but it can’t override the compiler-synthesized get
or set
blocks.
@testable
Apply this attribute to an import
declaration to import that module with changes to its access control that simplify testing the module’s code. Entities in the imported module that are marked with the internal
access-level modifier are imported as if they were declared with the public
access-level modifier. Classes and class members that are marked with the internal
or public
access-level modifiers are imported as if they were declared with the open
access-level modifier. And the imported module must be compiled with testing enabled.
1 |
@testable import ToDo_1 |
@objc
Apply this attribute to any declaration that can be represented in Objective-C—for example, nonnested classes, protocols, nongeneric enumerations (constrained to integer raw-value types), properties and methods (including getters and setters) of classes, protocols, and optional members of a protocol, initializers, and subscripts. The objc
attribute tells the compiler that a declaration is available to use in Objective-C code.
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 nonobjc
attribute.
1 2 3 4 5 6 |
func registerForKeyboardNotifications() { NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWasShown), name: NSNotification.Name.UIKeyboardDidShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillBeHidden), name: NSNotification.Name.UIKeyboardWillHide, object: nil) } @objc func keyboardWasShown(_ notification: Notification) { ... } |
@objcMembers
Apply this attribute to a class declaration, to implicitly apply the objc
attribute to all Objective-C compatible members of the class, its extensions, its subclasses, and all of the extensions of its subclasses.
1 2 |
@objcMembers class ABC: UIViewController { ... } |
@avaiable
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:
iOS
iOSApplicationExtension
macOS
macOSApplicationExtension
macCatalyst
macCatalystApplicationExtension
watchOS
watchOSApplicationExtension
tvOS
tvOSApplicationExtension
swift
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.
- unavailable
- introduced
- deprecated
- obsoleted
- message
- renamed
You can apply multiple available
attributes on a single declaration to specify the declaration’s availability on different platforms and different versions of Swift.
If an available
the attribute only specifies an introduced
an argument in addition to a platform or language name argument, you can use the following shorthand syntax instead:
1 2 |
@available(platform name version number, *) @available(swift version number) |
@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.
1 2 3 4 5 |
@discardableResult func abc() -> String { return "Test" } abc() |
@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:)
the method, or both. The declaration of the dynamicallyCall(withArguments:)
the method must have a single parameter that conforms to the ExpressibleByArrayLiteral
protocol.
@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.
1 |
@frozen public struct Array<Element> { ... } |
@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:
1 2 3 4 5 6 |
@main struct MyTopLevel { static func main() { // Top-level code goes here } } |
@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.
Type Attributes
You can apply them to only types.
autoclosure
Apply this attribute to delay the evaluation of an expression by automatically wrapping that expression in a closure with no arguments. You apply it to a parameter’s type in a method or function declaration, for a parameter whose type is a function type that takes no arguments and that returns a value of the type of the expression.
1 2 3 4 5 6 7 8 9 10 11 12 |
var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"] print(customersInLine.count) // Prints "5" let customerProvider = { customersInLine.remove(at: 0) } print(customersInLine.count) // Prints "5" print("Now serving \(customerProvider())!") // Prints "Now serving Chris!" print(customersInLine.count) // Prints "4" |
@escaping
Apply this attribute to a parameter’s type in a method or function declaration to indicate that the parameter’s value can be stored for later execution. This means that the value is allowed to outlive the lifetime of the call.
1 2 3 4 5 6 7 |
class NetworkManger { func apiHit(url: String, completion: @escaping ((JSON) -> Void)) { // logic goes here } } |
Switch Case Attributes
You can apply switch case attributes to switch cases only.
@unknonw
Apply this attribute to a switch case to indicate that it isn’t expected to be matched by any case of the enumeration that’s known at the time the code is compiled. It was introduced with @frozen and @nonfrozen enumerations.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { switch status { case .authorizedWhenInUse, .authorizedAlways: if CLLocationManager.locationServicesEnabled() { self.locationManager?.startUpdatingLocation() } case .restricted, .denied: openMapForLocation() case .notDetermined: break @unknown default: break } } |
Thank you for reading this article.