How do Swift and Objective-C see each other: bridging header, umbrella header, and the -Swift.h file?

4.8.1 · L3 · Interview

Predict first

Which generated header lets Objective-C code see your Swift classes?

// A: MyApp-Bridging-Header.h
// B: MyApp-Swift.h
// C: the umbrella header
  • A
  • B
  • C

Predict first

Can a framework target use a bridging header?

// A: yes, same as an app
// B: no, it uses an umbrella header and module map
  • A
  • B

Mental model. Two translators sit at a border, one in each direction. The bridging header is the list of words Swift is allowed to hear; the Swift header is the list the other side may use.

Two headers, one in each direction. For Swift to see Objective-C, an app target uses a bridging header (MyApp-Bridging-Header.h) that imports every ObjC header Swift needs; a framework cannot use one and instead exposes ObjC through its umbrella header and module map (public headers only). For Objective-C to see Swift, the compiler generates MyApp-Swift.h, containing only declarations marked @objc (or inheriting from NSObject), which Objective-C files #import.

The generated header explains most mixed-build puzzles. Put a header import in an Objective-C header and you risk a circular import; use a forward declaration (@class SwiftThing;) in headers and import -Swift.h in the .m. Anything not @objc is invisible to Objective-C. Swift packages can mix languages in recent toolchains, but check what your version supports before relying on it. Keep the bridging header lean: everything in it is visible to all of Swift in the target and slows incremental builds.

MyApp-Swift.h is generated from your @objc Swift declarations. The bridging header goes the other way.

Frameworks expose Objective-C through public headers and the umbrella header, so the module is self-contained.

Common traps

  • Importing -Swift.h in an Objective-C header. It creates a cycle. Use @class or @protocol forward declarations.
  • Expecting a framework to use a bridging header. It uses an umbrella header and module map.

They might follow up with

  • Why is a Swift class missing from -Swift.h? It is not @objc or not an NSObject subclass, or uses a type Objective-C cannot express.
  • Where does the module name come from? The product module name, which also names the generated header.

Related questions

  • 4.4.1 What do @objc, @objcMembers, @objc(name), dynamic and @nonobjc each do?
  • 4.4.2 Which Swift features cannot be seen from Objective-C?
  • 4.8.2 What does mixing Swift and Objective-C cost, and how do you keep the cost down?

What does mixing Swift and Objective-C cost, and how do you keep the… →