Skip to content
128 changes: 128 additions & 0 deletions TSPL.docc/ReferenceManual/Attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,134 @@ Most code can use the main actor instead of defining a new global actor.

[`GlobalActor`]: https://developer.apple.com/documentation/swift/globalactor

### implementation

Apply this attribute to a declaration
that provides a Swift implementation
for a declaration that's imported from another language.

For declarations that are defined in an Objective-C header,
Comment thread
amartini51 marked this conversation as resolved.
apply both the `objc` and `implementation` attributes
to an extension in Swift that provides the implementations.
Other code in Swift treats these implementations
as if they were implemented in Objective-C and imported into Swift.
The class that the extension extends must be imported from Objective-C,
not be a root class,
and not use lightweight generics.
The extension can't include any protocol conformances.
All declarations in this extension are implicitly marked with the `objc` attribute.
For example,
the following Objective-C header declares a class with one method:

```objc
NS_HEADER_AUDIT_BEGIN(nullability, sendability)
@interface MyClass
- (void)performSomeAction;
@end
NS_HEADER_AUDIT_END(nullability, sendability)
```

<!-- Omitted the header's conventional blank lines for compactness. -->

You implement the class and its method in Swift as follows:

```swift
@objc @implementation
extension MyClass {
func performSomeAction() { ... }
}
```

A member of the extension that matches a declaration in the header file
is known as a *member implementation*.
To be considered as a match,
a member implementation must meet the following requirements:

- Its selector and Swift name be the same as the declaration it implements.
If needed, you can use the `objc(custom:selector:)` attribute in Swift
and the `NS_SWIFT_NAME(custom(_:name:))` attribute in Objective-C.
- Its type matches the type of the declaration it implements,
Comment thread
amartini51 marked this conversation as resolved.
Outdated
Non-optional types in Objective-C can be implemented in Swift
either as non-optional or as an implicitly unwrapped optional.
Comment thread
amartini51 marked this conversation as resolved.
Outdated
- Its error handling (`throws`) and concurrency (`async`)
matches the declaration it implements.
Comment thread
amartini51 marked this conversation as resolved.
- It isn't marked `final` or `override`.
- Its access control level is `open`, `public`, `package`, or `internal`.
- It doesn't have any other traits
that would be incompatible with the member it implements,
like the `nonobjc` attribute, `class` modifier, or mutability,

Every member implementation in the extension
must match a member declared in the Objective-C header,
and every member declared in the Objective-C header
must have either a matching member implementation in Swift
or an implementation in Objective-C.
<!-- XXX TR: The SE proposal phases this as
“every member declared in the Objective-C header
must have a matching member implementation”
which suggests you can't have the implementation in an Objective-C .m file.
I'm assuming that's not the case because it would contradict
the advice that you can migrate the implementation one method at a time.
-->
Comment thread
amartini51 marked this conversation as resolved.

In addition to member implementations,
you can also write the following declarations in the extension,
which must not match a declaration in the Objective-C header:

- Overrides for superclass members.
You mark these declarations with `override` as usual.
- Helper members with a `fileprivate` or `private` access control level
that aren't marked `final`.
To access them from Objective-C,
either declare them in a header that's not visible to the Swift compiler
or access them using their selector.
- Helper members with `internal` or `private` access,
Comment thread
amartini51 marked this conversation as resolved.
Outdated
which are accessible only from other Swift code.
You mark these declarations `final`,
and they're implicitly marked with the `nonobjc` attribute.
For initializers, you apply the `nonobjc` attribute instead.
- APIs with `public` or `package` access,
which are only accessible to Swift clients.
You mark these declarations `final`,
and they're implicitly marked with the `nonobjc` attribute.
For initializers, you apply the `nonobjc` attribute instead.

<!--
XXX TR: Please confirm discussion of inits.
The proposed solution and detailed design sections of the SE proposal
frame these slightly differently.
-->
Comment thread
amartini51 marked this conversation as resolved.
Outdated

The extension can include declarations for stored properties and initializers,
which is an exception to the rule that these can't be declared in extensions.

If you provide an argument to the `objc` attribute,
the extension's members are placed in an Objective-C category with that name,
which must match an category declared in the Objective-C header file.
For example, if the header contains the following:

```objc
@interface MyClass (SomeCategory)
- (void)someCategoryMethod;
@end
```

The Swift code to implement `someCategoryMethod()` is as follows:

```swift
@objc(SomeCategory) @implementation
extension MyClass {
func someCategoryMethod() { ... }
}
```

Implementing an interface in Swift doesn't require any changes
to the interface declared in the Objective-C header file.
If you have an existing interface,
you can use this attribute
to replace its Objective-C implementation with a Swift one,
without changing the header file.
Comment thread
amartini51 marked this conversation as resolved.
Outdated

### inlinable

Apply this attribute to a
Expand Down