How to Use Attributes of Swift
The attributes of Swift is a powerful tool that helps us to design more reliable, concise, and flexible code.
In addition of @discardableResult
, @escaping
, @autoclosure
and so on that we usually use, Swift has many another attributes that we can use to write some ingenious usages.
Firstly, I list all attributes of Swift below
Name | Modifier Scope |
---|---|
available |
declaration of types, properties, or methods |
discardableResult |
declaration of methods |
dynamicCallable |
declaration of types |
dynamicMemberLookUp |
declaration of types |
frozen |
declaration of structures, or enumerations |
BKInspectable |
|
inlinable |
function, computed property, subscript, initializer, or deinitializer |
main |
declaration of structures, classes, or enumerations |
nonobjc |
method, property, initializer |
NSApplicationMain |
same as main |
NSCopying |
stored variable properties of classes |
NSManaged |
|
objc |
|
objcMembers |
|
propertyWrapper |
|
resultBuilder |
|
requires_stored_property_inits |
declaration of classes |
testable |
|
UIApplicationMain |
same as main |
usableFromInline |
same as inlinable |
warn_unqualified_access |
|
IBAction |
|
IBSegueAction |
|
IBOutlet |
|
IBDesignable |
|
IBInspectable |
|
autoclosure |
|
convention |
|
escaping |
|
unknown |
|
_marker |
Used to mark a marker-protocol. |
globalActor |
Used to custom a global actor. |
available
- The availability limitation for platforms and versions.
1 | @available(iOS 11.0, macOS 11.0, *) |
- The availability limitation for Swift version.
1 | @available(swift 5.0) |
- Indicates the type or function can’t be used in current context.
1 | @available( |
- Warns developers that the type or function will be deprecated.
1 | @available( |
discardableResult
1 | @discardableResult |
dynamicCallable
1 | @dynamicCallable |
- The
struct
,class
,enumeration
orprotocol
marked with@dynamicCallable
must have either the functiondynamicallyCall(withArguments:)
orfunc dynamicallyCall(withKeywordArguments:)
. - The arguments of the function
dynamicallyCall(withArguments:)
is conforming toExpressibleByArrayLiteral
. - The keyword arguments of the function
dynamicallyCall(withKeywordArguments:)
is conforming toExpressibleByDictionaryLiteral
and itsKey
must beExpressibleByStringLiteral
conformance.
Except dynamicCallable
, Swift provides another way to make a value can be called directly. The way is to write a method callAsFunction
for your type.
1 | struct Storage { |
Mind you, if you implement @dynamicCallable and callAsFunction at the same time, the callAsFunction will override the functionality of @dynamicCallable(will be ignored).
dynamicMemberLookup
dynamicMemberLookup attribute requires the struct, class, enum, or protocol to have a subscript(dynamicMember:)
method that accepts either ExpressibleByStringLiteral
or a key path
.
1 | @dynamicMemberLookup |
The argument member of the method must be ExpressibleByStringLiteral
conformance, usually be String
.
1 | @dynamicMemberLookup |
Using key path (supports KeyPath
, WriteableKeyPath
, or ReferenceWritableKeyPath
) as the dynamicMember’s type can support compile-time type checking.
frozen
Restricts modifiability of structures or enumerations in future versions to boost performance.
In library evolution mode, apply this attribute to structures or enumerations makes them cannot add, remove, or reorder enumeration cases or stored properties in future versions.
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.
Detail in documents
GKInspectable
Apply this attribute to expose a custom GameplayKit component property to the SpriteKit editor UI. Applying this attribute also implies the objc attribute
inlinable
& usableFromInline
Applying these two attributes to a function, method, computed property, subscript, initializer or deinitializer will expose their detailed implementation when being called as APIs. The caller will copy the implementation code directly to the calling context.
inlinable
is used for public
targets. usableFromInline
is use for internal
targets.
These modifiers can’t decorate private
or fileprivate
targets.
main
, NSApplication
, and UIApplication
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 marked as @main
must have a type method main
without any arguments or return values.
1 | @main |
The UIApplication
is used for iOS projects and the NSApplication
is used for macOS projects.
If you want to make an executable, you must provides at least one top-level entry point, as discussed in Top-Level Code
nonobjc
Apply this attribute to a method, property, or initializer declaration to suppress an implicit objc
attribute. The nonobjc
attribute tells the compiler to make the declaration unavailable in Objective-C language code.
NSCopying
Applying this attribute to a stored variable property of a class 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 NSCopying
.
NSManaged
Used in Core Data
.
objc
Apply this attribute to any declaration that can be represented in Objective-C code-for examples
nonnested classes
protocols
nongeneric enumerations(constrained to integer raw-value types)
properties
andmethods(including getters and setters) of classes
protocols
andoptional members fo a protocol
initializers
subscripts(including getters and setters)
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 nonobjc
attribute.
Applying the attribute with one argument to the declarations listed above can rename them for Objective-C.
1 | @objc class Storage: NSObject { |
objcMembers
Apply the attribute to a class declaration, to implicitly apply the objc
to all Objective-C compatible members of the class, its extensions, its subclasses, and all of the extensions of its subclasses.
Recommend to use objc
to replace of objcMembers
to decrease the binary size of you product and boost performance.
propertyWrapper
Detail in Learning Swift Again
resultBuilder
Detail in Swift5.4 New Feature ResultBuilder
requires_stored_property_inits
Apply this attribute to a class declaration to require all its stored properties within the class to provide a default value as part of their definition.
testable
Used in import
declaration. All internal
entities within the module imported with @testable
will be treated as public
in unit test.
All classes and class members of internal
or public
will be treated as open
in unit test.
warn_unqualified_access
Used in declarations of top-level functions, instance methods, or class or static methods.
Displaying a warning when you access a method marked with @warn_unqualified_access
attribute without a preceding qualifier.
1 | func test() { |
autoclosure
Used in argument declarations of methods. The commonest usage is to delay the passed value’s evolution when being called.
1 | func calculateComplexValue() -> Int { |
convention
Apply this attribute to decorate the type of a block. Then we can pass these decorated blocks to the arguments of C-pointer function or Objective-C block type when calling a method.
@convention(c)
: Defines a block as a C-pointer function.
1 | CGFloat myCFunction(CGFloat (callback)(CGFloat x, CGFloat y)) { |
@convention(oc)
: Defines a block as a Objective-C block.
1 | let animationsBlock : @convention(block) () -> () = { |
@convention(swift)
: Defines a pure Swift block.
escaping
Applying this attribute to a block argument of a function or method indicates the block argument might be called outside of the function’s scope.
unknown
Apply this attribute to the default
case of a enumeration switching. If the switching doesn’t match all cases of the enumerations, the compiler will throw an warning message(just a pure default
case will match all unmatched cases without any reminder. if the unfrozen enumeration adds some new cases, we might miss processing these cases).