> ## 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.

# Swift ObjC Attribute

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.

```swift theme={"dark"}
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.

```swift theme={"dark"}
@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.

```swift theme={"dark"}
@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.

```swift theme={"dark"}
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() {}
}
```

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor Swift Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
