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

4

147

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.

Sogdiana answered 21/7, 2014 at 22:15 Comment(4)
"I realize that Beta 3 eliminated the need for frameworks". How?Computation
(for live views) - editedSogdiana
I'm running into the same problem.Fugitive
Wow, your little edit there just made my life so much better - didn't hear of this change (eliminating the need for frameworks) anywhere and was banging my head with all these framework targets for live views for hours. Thank you so much for this @chrisco!Dunaj
M
262

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.

Molehill answered 22/7, 2014 at 4:22 Comment(19)
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.Sogdiana
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)Eyepiece
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?Glogau
@Glogau check out the "Importing Swift into Objective-C" section of this document: developer.apple.com/library/ios/documentation/Swift/Conceptual/…Molehill
@DeepFriedTwinkie, what umbrella file are you referring when you say: "Add the necessary headers to your umbrella file"? Thanks.Bhang
@Allan I've updated my answer with a brief description of an umbrella header.Molehill
@Molehill 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: #30095787. Thanks.Bhang
@Molehill 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: #31688848Vernice
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"Spacious
This is exactly what I needed. Adding them to the public section was the fix.Peck
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.Witter
@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.Checky
@Molehill 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'Stalag
@morroko not sure about that. You might want to look at this answer: https://mcmap.net/q/126842/-include-of-non-modular-header-inside-framework-moduleMolehill
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.!!Semipalatinsk
thank you for saving me lots of wasted hours! If i could upvote this more than once, i wouldAurelio
@Molehill Clean and build the framework erases all the settings. Is there any permanent solution to fix this issue?Otoscope
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.oMonterrey
This solution worked for me. I have noticed [productName].h file is in the project. declared all the headers in the same file.Cleopatracleopatre
S
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  
Stonefly answered 24/11, 2017 at 12:42 Comment(5)
Excellent! Thanks. Much preferred technique over making all the headers public.Palila
Strongly advise that solution against the others, and to look the link provided for detailed solutionMauriac
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: developer.apple.com/documentation/swift/…Prototherian
The header statement accepts a relative path. What do you do when you want to add the headers of another framework?Humiliate
@Humiliate fall back to umbrella-header approach (don't use this, if importing public headers from another framework)Encipher
A
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.

Aperient answered 16/7, 2016 at 14:48 Comment(3)
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?Togs
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 worldTragedian
@Tragedian I cannot really remember correctly what I did back than. I wish this problem has been addressed in later versions of Swift.Togs
B
1

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

enter image description here

Brusquerie answered 14/7, 2020 at 16:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.