Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Include -Swift.h in the umbrella header

I have a mixed Swift and Objective-C project. To access a Swift public API in Objective-C, the API consumer currently has to import "MyModule-Swift.h". I already have a Objective-C umbrella header called "MyModule.h". But, importing "MyModule.h" is not going to work for the Swift APIs. I tried importing "MyModule-Swift.h" in the umbrella header, but it doesn't find it (I'm assuming since it is generated on the fly by Xcode).

Any suggestions so that an API consumer can always import "MyModule.h" to use public APIs written in Swift/Objective-C will be really appreciated.

====================================================================

Edit: I apologize for not taking the time to properly frame the question. I have a framework called MyModule.

I have a Objective-C class called ABUser,

@interface ABUser: NSObject

- (void)walk;

@end

I wanted to add new behavior to this class using Swift, so I defined an extension

extension ABUser {

func swiftWalk()

}

Now, say I wanted to access the swiftWalk method defined on ABUser from an Objective-C app, I would have to #import <MyModule/MyModule-Swift.h>. #import <MyModule/MyModule.h> would work if I wanted to use the walk method. This is assuming the umbrella header MyModule.h imports ABUser.h.

I always wanted the Objective-C app to #import <MyModule/MyModule.h> and never have to worry about whether an API was written in Objective-C or Swift in the framework. So, I tried importing MyModule-Swift.h in the umbrella header MyModule.h. But, my Objective-C app didn't compile if do that. Not sure, if this is because MyModule-Swift.h is generated by Xcode on the fly during the build process.

Edit 2: Added a sample project to reproduce this issue here: https://github.com/priteshshah1983/MyObjectiveCApp

The relevant code is in ViewController.m. The build will fail with the master branch. To get it work, checkout the working branch.

like image 768
pshah Avatar asked Oct 08 '15 18:10

pshah


People also ask

What is an umbrella header?

The umbrella header is the 'master' header file for a framework. Its use is that you can write #import <UIKit/UIKit.h> instead of #import <UIKit/UIViewController.h> #import <UIKit/UILabel.h> #import <UIKit/UIButton.h> #import <UIKit/UIDatePicker.h> and so on.

How do you use bridging headers in Swift?

Alternatively, you can create a bridging header yourself by choosing File > New > File > [operating system] > Source > Header File. Edit the bridging header to expose your Objective-C code to your Swift code: In your Objective-C bridging header, import every Objective-C header you want to expose to Swift.

How do I add an Objective-C framework to a Swift project?

The correct approach is as follows: Import your Objective C framework by dragging and dropping the framework into an Xcode 6 Swift project. Create a new Objective C file in your project (File->New->File [Objective C for iOS]). Accept the prompt (agree) to create a bridging header file between Objective C and Swift.


1 Answers

The reason that using @import MyModule; worked, is that "modules are a packaging together of the framework executable and it's headers" (from this SO post).

In other words, when you @import MyModule;, Objective-C automatically imports all the swift and Objective-C headers related to the module, while you cannot include the swift header from the umbrella header. I suggest you take a look at the differences between @import and #import in the linked SO answer.

like image 102
vigneshv Avatar answered Sep 28 '22 09:09

vigneshv