Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xcode generated umbrella header for framework does not import Foundation when @objc inference is turned off

Tags:

xcode

ios

swift

I have a framework written entirely in Swift, and it's included in an app that uses a mix of Objective-C and Swift, i.e.

#import "MyFramework-Swift.h"

If Swift 3 @objc inference is turned ON for the framework target then everything compiles and runs fine. If Swift 3 @objc inference is turned OFF then the framework itself will compile, but the file that it's included in does not and spits out a bunch of errors like:

Unknown type name 'NSArray' or Unknown type name 'NSError'

The imports in the Objective-C file where I'm trying to use this framework essentially look like this (i.e. Foundation is being imported before trying to import the swift framework):

@import Foundation;
#import <OtherNonSystemHeaders.h>
#import "ThisFilesHeader.h"
#import "MyFramework-Swift.h"

If I open up the header file that Xcode generates there's a section about 150 lines down that looks like this:

#if __has_feature(modules)
@import ObjectiveC;
#endif

And if I manually change it to this it will compile and run.

#if __has_feature(modules)
@import ObjectiveC;
@import Foundation;
#endif

Obviously that's not a real solution since it gets overwritten any time Xcode regenerates that header, but I can't understand why turning off @objc inference is causing that import to disappear. I have manually marked certain methods as @objc, all the classes in the framework subclass NSObject, and each file imports Foundation.

I thought this might be a bug, but this happens both with Xcode 9.2 and 9.3, and clearly people are able to turn off @objc inference since it's now a recommended setting. But I am truly at a loss.

like image 587
Mike Avatar asked Feb 23 '18 19:02

Mike


People also ask

What is Modulemap?

Modulemap exposes C header files for external binaries. It is a bridge between module and headers. Modulemap helps to convert #include, #import -> @import because it has a mapping between module name and headers inside. Also modulemap helps to create standalone additional modules and submodules.


1 Answers

This sounds like you're missing @import Foundation; in your ObjC prior to:

#import "MyFramework-Swift.h"

ObjC files should @import Foundation; themselves. This is often also placed in the precompiled header (.pch) for performance reasons, but each .m should still import everything it needs, including Foundation.

Typically I recommend the following layout for .m files:

@import ...System Headers...

#import "Non-system framework headers"

#import "Local headers"

#import "Project-Swift.h"
like image 106
Rob Napier Avatar answered Oct 05 '22 23:10

Rob Napier