145

I just upgraded to Xcode 6 Beta 4 and have a framework that I created for Live Views in Beta 2. Due to another swift bug, I needed to use some Obj-C code. When upgrading though, I get the following error:

error: using bridging headers with framework targets is unsupported

I have not seen anything in the release notes, or found any other migration path. Has anyone else seen this and arrived at a solution?

I realize that Beta 3 eliminated the need for frameworks for live views, but it makes sense in my case if I can get it to work. I can remove it though as a fallback, but would prefer to use a framework if they are not totally broken in Beta 4.

Community
  • 1
  • 1
Chris Conover
  • 8,889
  • 5
  • 52
  • 68

4 Answers4

259

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.

Community
  • 1
  • 1
DeepFriedTwinkie
  • 3,865
  • 1
  • 21
  • 21
  • 3
    Thanks for the succinct answer (marked as such). I had read that section but was confused as to the distinction between Umbrella and Bridging header. – Chris Conover Jul 22 '14 at 17:58
  • What do you mean by this, "Remove references to the header file in the build settings for the framework"? (I don't have exact references to the header file but the directory is part of the search paths) – cynistersix Nov 18 '14 at 18:32
  • And what's for the other way around? What should I do in order to use the Swift classes in my framework Objective-C code? – zaxy78 Jan 29 '15 at 10:20
  • 1
    @zaxy78 check out the "Importing Swift into Objective-C" section of this document: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html#//apple_ref/doc/uid/TP40014216-CH10-XID_77 – DeepFriedTwinkie Jan 29 '15 at 20:06
  • 4
    @DeepFriedTwinkie, what umbrella file are you referring when you say: "Add the necessary headers to your umbrella file"? Thanks. – Allan Macatingrao May 07 '15 at 03:59
  • @Allan I've updated my answer with a brief description of an umbrella header. – DeepFriedTwinkie May 07 '15 at 13:42
  • @DeepFriedTwinkie Thanks. Actually Im creating a swift dynamic framework, and I need to include file that has been added to my project using cocoapods. You can check it here: After removing the header file, this happened: http://stackoverflow.com/questions/30095287/swift-dynamic-framework-include-of-non-modular-header. Thanks. – Allan Macatingrao May 07 '15 at 14:47
  • @DeepFriedTwinkie I'm trying to create a custom frame work in Swift that needs ObjC framework that's managed via CocoaPods. Perhaps you know the answer: http://stackoverflow.com/questions/31688348/ios8-custom-swift-framework-accessing-external-framework-written-in-objective-c – user1107173 Jul 28 '15 at 22:50
  • Citing this comment about where is the umbrella header, in case anyone else also doesn't know this: *"It will be a .h file with the same name as your framework containing the version number and version string. Look for FOUNDATION_EXPORT double {framework name}. – Nate Cook"* – User Oct 15 '15 at 11:59
  • 2
    This is exactly what I needed. Adding them to the public section was the fix. – olivaresF Jan 04 '16 at 05:04
  • 25
    Am I correct in assuming then that any classes I want to keep private in my framework that must be used by a swift class must now be made public to anyone using my framework? Doesn't seem like an ideal solution. – ospr Jan 15 '16 at 18:27
  • @ospr-- I'm wondering this exact thing too. I have various Objective-C classes I want to keep internal to my framework and not expose publicly. – Chris Prince Jan 17 '16 at 03:52
  • @DeepFriedTwinkie hi I followed each steps after adding classes in umbrella header file I am getting this error Include of non-modular header inside framework module 'SpectrumLibrary' – Gajendra Rawat Sep 01 '16 at 13:44
  • @morroko not sure about that. You might want to look at this answer: http://stackoverflow.com/a/28552525/730452 – DeepFriedTwinkie Sep 01 '16 at 16:48
  • One of my project has two framework targets: one for Mac OS and other is for iOS, Mac OS with bridging header works just fine, iOS bridging header complains the above error.!! – Sunil Chauhan Sep 29 '16 at 19:03
  • thank you for saving me lots of wasted hours! If i could upvote this more than once, i would – Lena Bru Feb 01 '17 at 10:59
  • @DeepFriedTwinkie Clean and build the framework erases all the settings. Is there any permanent solution to fix this issue? – arunit21 Jul 23 '19 at 06:10
  • This doesn't seem to be working for me. I'm getting errors like: Undefined symbols for architecture x86_64: "_OBJC_CLASS_$_MyClass", referenced from: objc-class-ref in MyOtherClass.o – Mark Bridges Jul 28 '19 at 00:09
  • This solution worked for me. I have noticed [productName].h file is in the project. declared all the headers in the same file. – Sravan Aug 22 '19 at 07:12
39

There are two possibilities. Adding the necessary headers to the umbrella header file and making them public is one way. However, this is a problem if the headers should be available to Swift, but not public.

The second possibility which will make internal headers available to Swift is described in detail here. Essentially, a module map similar to the following needs to be created:

module AwesomeKitPrivate {  
  header "../InternalClass.h"
  export *
}

This can then be included in XCode using the setting:

SWIFT_INCLUDE_PATHS = $(SRCROOT)/AwesomeKit/ProjectModule  
Simon
  • 2,721
  • 1
  • 13
  • 15
Jan Rüegg
  • 9,587
  • 8
  • 63
  • 105
  • 4
    Excellent! Thanks. Much preferred technique over making all the headers public. – David H Mar 02 '18 at 19:56
  • Strongly advise that solution against the others, and to look the link provided for detailed solution – Tancrede Chazallet Aug 14 '18 at 08:43
  • This is the right answer imo but depending on what you're trying to achieve you may be able to get away with using some Apple-provided macros which help a lot with Swift-Objc interop: https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization – Joe Susnick Aug 12 '19 at 23:24
  • 1
    The `header` statement accepts a relative path. What do you do when you want to add the headers of another framework? – Georgios Aug 23 '19 at 14:50
  • @Georgios fall back to umbrella-header approach (don't use this, if importing *public* headers from *another* framework) – Top-Master Sep 11 '21 at 19:26
15

See Importing Objective-C into Swift .

To import Objective-C code into Swift from the same framework

  1. Under Build Settings, in Packaging, make sure the Defines Module setting for that framework target is set to “Yes".
  2. In your umbrella header file, import every Objective-C header you want to expose to Swift. For example:

        #import "XYZ/XYZCustomCell.h"
        #import "XYZ/XYZCustomView.h"
        #import "XYZ/XYZCustomViewController.h"
    
  3. Make the included files public in the framework's "Headers" section of its "Build Phases".

  4. Clean and rebuild.

Swift will see every header you expose publicly in your umbrella header. The contents of the Objective-C files in that framework will be available in any Swift file within that framework target automatically, without any import statements. Use your custom Objective-C code with the same Swift syntax you use with system classes.

let myOtherCell = XYZCustomCell()
myOtherCell.subtitle = "Another custom cell"

Important: the "umbrella header file" means the file {ModuleName}.h. BTW, the target name is {ModuleName}.framework.

Ralph Shane
  • 151
  • 1
  • 4
  • 2
    I want to use objc files inside my modules Swift file but I don't want to expose them to other modules. How can I do so? – Sazzad Hissain Khan Dec 04 '19 at 04:38
  • Hi @SazzadHissainKhan, have you managed to solve your problem? I'm struggling with the same issue. I want my objc headers to be visible to Swift but not exposed to the outer world – Ivan Nov 06 '21 at 05:00
  • @Ivan I cannot really remember correctly what I did back than. I wish this problem has been addressed in later versions of Swift. – Sazzad Hissain Khan Nov 06 '21 at 22:58
1

In my case just removing Objective-C Bridging Header setting from my framework's Build Settings helped.

enter image description here

Denis Kutlubaev
  • 15,320
  • 6
  • 84
  • 70