In Swift, @objc
and @nonobjc
are two attributes that affect the interoperability between Swift and Objective-C. This enables a gradual transition from Objective-C to Swift, promotes code reuse, and provides access to a vast array of libraries and APIs in both languages.
@objc
is used to expose a method, property, or class to Objective-C@nonobjc
is used to explicitly hide an entity from Objective-CThe @objc
attribute exposes a Swift declaration to Objective-C and the Objective-C runtime. This is useful when you want to interact with Objective-C frameworks, such as UIKit, or use features that require Objective-C, such as selectors, key-value coding, or dynamic dispatch.
To use @objc
in Swift, you need to mark the class, method, property, or other declaration that you want to expose to Objective-C with the @objc
attribute. For example:
// A Swift class that inherits from NSObject and is exposed to Objective-C
@objc class Person: NSObject {
// A Swift property that is exposed to Objective-C
@objc var name: String
// A Swift method that is exposed to Objective-C
@objc func sayHello() {
print("Hello, I'm \(name)")
}
}
You can also use @objcMembers
to expose all members of a class to Objective-C without marking them individually. For example:
// A Swift class that inherits from NSObject and exposes all its members to Objective-C
@objcMembers class Person: NSObject {
// A Swift property that is exposed to Objective-C implicitly
var name: String
// A Swift method that is exposed to Objective-C implicitly
func sayHello() {
print("Hello, I'm \(name)")
}
}
Note that not all Swift declarations can be exposed to Objective-C. For example, Swift enums, structs, generics, tuples, and closures cannot be represented in Objective-C. If you try to mark them with @objc
, you will get a compiler error.
The @nonobjc
attribute is used in Swift to indicate that a certain declaration should not be exposed to Objective-C. It is essentially the opposite of @objc
. When you mark a declaration with @nonobjc
, you’re specifying that it should not be accessible from Objective-C code.
class MySwiftClass: NSObject {
// Exposed to Objective-C
@objc func methodExposedToObjC() {
print("This method is exposed to Objective-C.")
}
// Not exposed to Objective-C
@nonobjc func methodNotExposedToObjC() {
print("This method is not exposed to Objective-C.")
}
}
You can use @nonobjc
to suppress an implicit @objc
attribute that is added by the compiler in some cases. For example, if you override a method or satisfy a requirement from a protocol that has the @objc
attribute, the compiler will also add the @objc
attribute to your declaration. You can use @nonobjc
to prevent that and make your declaration unavailable in Objective-C.
Another use case for @nonobjc is to resolve name conflicts between Swift and Objective-C declarations. For example, if you have a Swift method that has the same name as an Objective-C method, but different parameters or return type, you can use @nonobjc
to avoid a compiler error.
Note that you cannot use @nonobjc
on protocols, because protocols are never implicitly exposed to Objective-C. You can only use @nonobjc
on methods, properties, subscripts, or initializers.