Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The @objc attribute is a compiler directive that exposes Swift declarations to the Objective-C runtime and allows Objective-C code to interact with Swift APIs. Applying this attribute instructs the Swift compiler to generate the necessary Objective-C metadata and message-passing thunks for the annotated entity.

Syntax and Symbol Renaming

By default, the Swift compiler infers the Objective-C symbol name from the Swift declaration. You can explicitly provide an Objective-C name by passing an identifier to the attribute. This is required when the Swift name is invalid in Objective-C or when conforming to a specific Objective-C naming convention.
import Foundation

// Default inference
@objc class NetworkManager: NSObject {
    @objc var isConnected: Bool = false
    
    @objc func connect() {}
}

// Explicit symbol renaming
@objc(XYZAdvancedNetworkManager)
class AdvancedNetworkManager: NSObject {
    
    // Renaming a method and its parameters for Objective-C
    @objc(updateWithConfiguration:forceRefresh:)
    func update(configuration: [String: Any], force: Bool) {}
}

Applicability and Type Compatibility

The @objc attribute can be applied to classes, protocols, methods, properties, initializers, subscripts, enumerations, and extensions. Applying @objc to an extension is a common pattern that implicitly exposes all eligible members within that block to Objective-C without requiring individual annotations. The Swift compiler enforces strict type compatibility rules. Every type in the annotated declaration’s signature (parameters, return types, and property types) must be representable in Objective-C. Compatible Types:
  • Objective-C classes (NSObject and its subclasses).
  • Swift classes inheriting from an Objective-C class.
  • @objc protocols.
  • Bridged Swift standard library types (e.g., Int, Double, String, Array, Dictionary).
  • Swift enumerations with an integer raw type (e.g., Int, Int8, UInt16, Int32).
Incompatible Types:
  • Swift structures (struct).
  • Tuples.
  • Generic types or methods.
  • Swift enumerations with associated values or non-integer raw types.
  • Swift-only protocols.
@objc class DataProcessor: NSObject {
    // Valid: String and Int are bridged to NSString and NSInteger
    @objc func process(data: String) -> Int { return 0 }
    
    // Invalid: Tuples cannot be represented in Objective-C
    // @objc func fetch() -> (String, Int) { return ("", 0) }
}

// Valid: Integer-backed enum exposed to Objective-C
@objc enum Status: Int16 {
    case active
    case inactive
}

// Valid: Applying @objc to an extension implicitly exposes all eligible members
@objc extension DataProcessor {
    func reset() {} // Implicitly @objc
    func flush() {} // Implicitly @objc
}

Implicit @objc Inference

In certain contexts, the Swift compiler implicitly applies the @objc attribute to declarations, meaning explicit annotation is not required:
  1. Overriding a method or property from an Objective-C superclass.
  2. Implementing a requirement from an @objc protocol.
  3. Declarations marked with specific Interface Builder or Core Data attributes (@IBAction, @IBOutlet, @IBInspectable, @NSManaged).

The @objcMembers Attribute

To avoid annotating individual members of a class, the @objcMembers attribute can be applied to the class declaration. This implicitly applies the @objc attribute to all eligible members of the class, its extensions, and its subclasses.
@objcMembers
class Configuration: NSObject {
    var timeout: Double = 30.0 // Implicitly @objc
    var retries: Int = 3       // Implicitly @objc
    
    // Not exposed to Objective-C due to incompatible type (Tuple)
    var metadata: (String, String)? 
}

@objc vs. dynamic Dispatch

The @objc attribute dictates visibility to the Objective-C runtime, but it does not strictly dictate the dispatch mechanism. By default, Swift uses static or vtable dispatch for performance, even for @objc methods, when called from Swift code. To force a declaration to use dynamic dispatch via Objective-C message passing (objc_msgSend), it must be marked with both @objc and the dynamic modifier. However, the dynamic modifier is independent of @objc. You can apply dynamic to Swift structures or non-Objective-C classes to enable Swift’s native dynamic dispatch (often used with @_dynamicReplacement). The @objc attribute is only required alongside dynamic when the dynamic dispatch must specifically route through the Objective-C runtime.
class Session: NSObject {
    // Exposed to Obj-C, but may still be statically dispatched in Swift
    @objc func start() {} 
    
    // Exposed to Obj-C AND forced to use Objective-C message passing
    @objc dynamic func terminate() {} 
}

struct NativeConfiguration {
    // Native Swift dynamic dispatch, completely independent of Objective-C
    dynamic func update() {}
}
Master Swift with Deep Grasping Methodology!Learn More