86

I'm successfully calling my Swift classes from Objective C (for target 'MyApp') via the import statement:

#import "MyApp-Swift.h"

I've now created a new target called "MyAppLite"

When I compile the new target, I get errors because "MyApp-Swift.h" is required by the code, but the compiler is creating "MyAppLite-Swift.h"

So, I need to create a conditional Swift/ObjC header #import for the target I'm compiling against.

How can this be done, or is there a better way?

8 Answers 8

98

It is also possible to set the Product Module Name setting in Build Settings to be the same across your modules (I set it to $(PROJECT_NAME)), so that the <project>-Swift.h file that is generated has the same name across all modules. This eliminates the need for adding/checking preprocessor macros.

Sign up to request clarification or add additional context in comments.

7 Comments

When you create your first Swift-file in your project, xcode will ask you to add the bridging header to the project. In my case it only added the needed config to the first build target. So I also needed to fix the other build targets by configuring the Objective-C Bridging Header
I found that this caused issues in the build process, and that when switching between them, I needed to clean the build folder. I believe that because they all share the same project name, they all build to the same folder.
I"m not sure, but my feeling is that messing with the Product Module Name will affect something later on, probably when submitting to the App Store ;)... changing the Objective-C Generated Interface Header Name as described in the other answer has no implications.
@Yar Just saw your comment. That was my feeling initially but the app has been in the App Store for a while and it hasn't been an issue. But if I was using the latest version of Xcode, I'd use Mike Fay's solution tbh. This answer was made before SWIFT_MODULE_NAME was available.
God bless you! Using same module name across all my targets save me from crappy issue with custom swift class in mixed Swift/ObjC project which happens only in release build!!! Thanks a lot!
|
69

The best way I've found to address this issue is in your Xcode shared project settings. You can search for the following setting:

Objective-C Generated Interface Header Name*

If you set that value to a common header name, such as "MyProject-Swift.h", it will be applied to each of your targets and you can safely use the import declaration in any of your Objective-C files. This allows you to continue using unique product module names for each target, if needed.

I've tested this in Xcode Version 6.4 (6E35b).

*Note: This will appear under your Swift compiler settings, which are only visible if you have Swift source files added to your project. Additionally, if a target doesn't have any Swift source associated with it, the Swift compiler options will not be visible for that target's build settings.

Good luck!

7 Comments

This is the best solution IMO.
The original value of this is $(SWIFT_MODULE_NAME)-Swift.h... so while this answer is awesome, I'd love to know how to adjust the SWIFT_MODULE_NAME for the module.
While I'm here, I'd recommend using some obvious name to reduce confusion, e.g., MidiDesignerAllTargets-Swift.h Thanks for this great answer, it's a great find.
This is the best solution if you are using Xcode 7+.
It is definitely still available in Version 8.3.3 (8E3004b).
|
54

Previous answers have some problems if you decide to rename your targets or project, or use SWIFT_MODULE_NAME as intended.

The most universal solution is to change SWIFT_OBJC_INTERFACE_HEADER_NAME (“Objective-C Generated Interface Header Name”) under Project's, not Targets, Build Settings, to:

  • $(PROJECT_NAME)-Swift.h — one per project;
  • $(SWIFT_MODULE_NAME)-Swift.h — one per module (default value).

enter image description here

4 Comments

the cleanest of all solutions.Xcode 8.3.3, Swift 3, make sure the common/shared swift files belong to each target, all works after this.
How to handle "$(PROJECT_NAME)-Swift.h file not found" error like warnings?
This should be accepted Answer as it shows some more details though @C0D3LIC1OU5 's answer was good enought
This is what I'm looking for. Thank you for your answer.
5

Well, the only way I can fix is to...

#ifdef IS_LITE
#import "MyApp_Lite-Swift.h"
#else
#import "MyApp-Swift.h"
#endif

Note that if there's any 'illegal' chars in my Product Module Name, they need to be replaced with underscores.

Hope that helps!

2 Comments

This worked for me, as the accepted answer caused build issues when switching between targets.
what's IS_LITE?
5

I put the appropriate #import <project>-Swift.h statement in a prefix header file (<project>-Prefix.pch) defined/added for each build (target/scheme).

1 Comment

This has the advantage of making it more convenient to use Swift classes in Objective-C, and more consistency between the Swift experience, where headers do not need to be explicitly imported, and the Objective-C experience.
1

pickture will tell you all

  1. second targets name xxx and xxx-ih

enter image description here

  1. select first target tap build setting -> find Objective-C Bridging Header set xxx-bridging-Header.h and Objective-C Generated Interface Header Name set xxx-Swift.h enter image description here

  2. select second target and same step 2 enter image description here

Comments

1

Also check SWIFT_INSTALL_OBJC_HEADER to be YES under "Swift Compiler - General". It's default value should be YES, bug it's NO by default. 🤷

config

enter image description here

1 Comment

This is what was missing for me, thanks
0

The only working way is the following :

1- from first target (which has a working bridging) Build Setting select Objective C Bridging Header
2- Copy Objective C Bridging Header
3- open the other target Build Setting
4- Paste it 5- change the header file to your new header file (i.e target B.h)

(now you have this option for two target)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.