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.