@objc, applied to a class member, exposes it to Objective-C's runtime — required for anything that needs Objective-C's dynamic dispatch, like KVO (key-value observing) or being called from Objective-C source directly. Subclassing NSObject is often necessary alongside @objc, since many Objective-C-facing behaviors assume that base class. Critically, Swift-only language features — structs, enums with associated values, generics, top-level (non-method) functions, and tuples — cannot be exposed to Objective-C at all, since Objective-C's runtime has no representation for them; only class-based, sufficiently simple Swift constructs can bridge. A bridging header lets a mixed Swift/Objective-C project import Objective-C headers directly into Swift code.
@objc: exposing a Swift class member
Without @objc, greet() simply isn't visible to Objective-C code or the Objective-C runtime at all — required specifically when Objective-C code needs to call this method, or when a mechanism like KVO needs runtime access to it.
class Greeter: NSObject {
@objc func greet(name: String) -> String {
return "Hello, \(name)!"
}
}
// now callable from Objective-C code as: [greeter greetWithName:@"Alice"]What genuinely cannot bridge to Objective-C
Every one of these fails to compile with @objc — Objective-C's runtime simply has no representation for a value type, an enum carrying data, or a generic parameter; only class-based, sufficiently simple constructs can bridge.
// @objc struct Point { } // COMPILE ERROR — structs can't bridge at all
// @objc enum Result { case success(String) } // COMPILE ERROR — associated values can't bridge
// @objc class Box<T> { } // COMPILE ERROR — generics can't bridge
@objc class Point2 : NSObject { // fine — a CLASS with simple, bridgeable members can bridge
@objc var x: Double = 0
@objc var y: Double = 0
}Bridging headers: mixing Swift and Objective-C in one project
The bridging header imports existing Objective-C headers so their classes become directly usable from Swift code in the same project — the standard mechanism for incrementally adopting Swift inside an established Objective-C codebase.
#import "LegacyObjCClass.h"
// now LegacyObjCClass is directly usable from any Swift file in this project