Objective-C Bridging Header for Frameworks

Objective-C Bridging Header for frameworks

I found a Objective-C Bridging Header setting in the target Build Settings. It was hidden by default. Check All instead of Basic.

In recent Xcode versions this solution would give the error Using bridging headers with framework targets is unsupported.

The workaround I've been using is to make the C-header public in the file inspector and import it in MyFramework.h like this example:

#import <MyFramework/MyObjectiveC.h>

How to change the C-header to public

Open your C-header and view the inspector by clicking in the upper right corner. To view the file inspector, click the file icon in the upper right corner.

Sample Image

Xcode 6 / Beta 4: using bridging headers with framework targets is unsupported

As the error states, bridging headers are not allowed in Frameworks. The Importing Code from Within the Same Framework Target section of the Mix & Match apple documentation hints at this. As they say, you need to "In your umbrella header file, import every Objective-C header you want to expose to Swift".

However, I discovered that you may also need to make those specific headers public as well. This answer reviews why and how to do that: Swift compiler error: "non-modular header inside framework module".

So, do this:

  1. Remove your bridging header file.
  2. Remove references to the bridging header file in the build settings for the framework
  3. Add the necessary headers to your umbrella file ([ProductName].h)
  4. Make the included files public in the framework's "Headers" section of its "Build Phases".
  5. Clean and rebuild.

Note: The "umbrella header file" is a file (named [ProductName].h) that generally represents all public headers of a framework. It is usually just a list of #import statements to other headers contained in the framework. In Xcode, if you open UIKit.h, you will see a good example of an umbrella file.

Xcode can't find Bridging header when loading Framework

Frameworks with mixed Swift and Objective-C code do not need (and should not have) a bridging header.

First make sure that your framework's build settings includes "Defines Module: Yes".

Then, your framework should already have an umbrella header, this is the header with the same name as your framework with stuff like this in it

//! Project version number for MyFramework.
FOUNDATION_EXPORT double MyFrameworkVersionNumber;

//! Project version string for MyFramework.
FOUNDATION_EXPORT const unsigned char MyFrameworkVersionString[];

Any Objective-C stuff that you want to be visible to Swift needs a header with public membership which is imported into that umbrella header like this #import <MyFramework/MyHeaderName.h>. Note that you need to apply this rule recursively: if you import an Objective-C header in the umbrella header, anything it imports also needs to be public and in the umbrella header.

This can be a little tricky if some of your Objective-C headers have unnecessary imports, or import stuff that you don't want to be public in your framework. You may need to restructure you code a bit so that you have a clear separation between public and private headers.

If you do that, all of that public Objective-C code should be automatically usable in the framework's Swift code, without any bridging header.

Official docs here: https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/importing_objective-c_into_swift

Multiple Objective C bridging headers in IOS project target

Sample Image

Create Separate bridging header for each Target.

Select Your Target -> Build Settings -> Swift Compiler.

Edit Objective-C Bridging Header Objective-C Generated Interface Header Name with Separate Target's Bridging Header.

How do I create an Objective-C bridging header?

You have to create a new objective c class:

You select New File

then

select cocoa touch class

then you name it and specify as objective-c class at language

select objective-c as language

then you select your directory and hit create. At this point xcode is going to ask you whether or not you want to create bridging header. Yep do it.

Sample Image

And at the end it should look more or less like this at your project.

Job done

hope that helps you.

What is the use of bridging header? Should we avoid using bridging header?

Apple has written a great book that covers this in depth. It can be found here:

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html

I will quote it to answer your questions:

"What is the use of bridging header?
Is it just for using Objective-C and Swift code in the same project?"

To import a set of Objective-C files in the same app target as your Swift code, you rely on an Objective-C bridging header to expose those files to Swift. Xcode offers to create this header file when you add a Swift file to an existing Objective-C app, or an Objective-C file to an existing Swift app.

The answer to this question is yes. It is just there to make Swift and Objective-C work together in the same project.

"Should we avoid using bridging header? Say, if there are two third party library which are very similar; one of them is in Objective-C and other is in Swift. Should we use the Swift library or use Objective-C library. Are there any downside of using bridging headers?"

There are always tradeoffs. The first answer to this is no you should not avoid using a bridging header; however, as far as third party libraries you have to look at many factors. Which one has more functionality? Is it being maintained and/or added to frequently?

Using an Objective-C library will also add things to be aware of and work around. From the book:

Troubleshooting Tips and Reminders


Treat your Swift and Objective-C files as the same collection of code, and watch out for naming collisions.

If you’re working with frameworks, make sure the Defines Module (DEFINES_MODULE) build setting under Packaging is set to “Yes".

If you’re working with the Objective-C bridging header, make sure the Objective-C Bridging Header (SWIFT_OBJC_BRIDGING_HEADER) build setting under Swift Compiler - Code Generation is set to a path to the bridging header file relative to your project (for example, “MyApp/MyApp-Bridging-Header.h").

Xcode uses your product module name (PRODUCT_MODULE_NAME)—not your target name (TARGET_NAME)—when naming the Objective-C bridging header and the generated header for your Swift code. For information on product module naming, see Naming Your Product Module.

To be accessible and usable in Objective-C, a Swift class must be a descendant of an Objective-C class or it must be marked @objc.

When you bring Swift code into Objective-C, remember that Objective-C won’t be able to translate certain features that are specific to Swift. For a list, see Using Swift from Objective-C.

If you use your own Objective-C types in your Swift code, make sure to import the Objective-C headers for those types before importing the Swift generated header into the Objective-C .m file you want to use your Swift code from.

Swift declarations marked with the private modifier do not appear in the generated header. Private declarations are not exposed to Objective-C unless they are explicitly marked with @IBAction, @IBOutlet, or @objc as well.

For app targets, declarations marked with the internal modifier appear in the generated header if the app target has an Objective-C bridging header.

For framework targets, only declarations with the public modifier appear in the generated header. You can still use Swift methods and properties that are marked with the internal modifier from within the Objective-C part of your framework, as long they are declared within a class that inherits from an Objective-C class. For more information on access-level modifiers, see Access Control in The Swift Programming Language (Swift 2.2).

How to import obj c framework into swift bridging header?

Now I've found the answer. The problem is that the framework doesn't stored inside the project folder but in download folder. And yeah, Facebook dev guide told me to drag the framework straight from where the framework is downloaded, and I didn't check the 'copy files if needed' checkbox when importing. From this answer, I found out that I need to fill in search path to the framework base folder in order for Xcode to be able to find it. Thanks for everyone for answering.



Related Topics



Leave a reply



Submit