82

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?

Pang
  • 9,564
  • 146
  • 81
  • 122
Fittoburst
  • 2,215
  • 2
  • 21
  • 33

7 Answers7

96

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.

user2067021
  • 4,399
  • 37
  • 44
C0D3LIC1OU5
  • 8,600
  • 2
  • 37
  • 47
  • 1
    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` – Kevin R Feb 26 '15 at 13:15
  • 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. – Saltymule Apr 23 '15 at 18:08
  • 11
    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. – Dan Rosenstark Oct 17 '15 at 19:42
  • 2
    @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. – C0D3LIC1OU5 Dec 10 '15 at 16:35
  • 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! – Vitalii Gozhenko Sep 24 '17 at 21:38
  • @boraseoksoon This answer is a little dated. I'd go with the answer by Mike Fay for recent XCode versions – C0D3LIC1OU5 Aug 20 '18 at 15:01
  • This is not really the correct answer, I would go with the second most upvoted answer – Sam Furlong Sep 23 '19 at 16:18
67

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!

Mike Fay
  • 856
  • 6
  • 8
52

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

Dmitry Isaev
  • 3,888
  • 2
  • 37
  • 49
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!

Fittoburst
  • 2,215
  • 2
  • 21
  • 33
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).

Will
  • 51
  • 1
  • 1
  • 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. – paulmelnikow Feb 11 '18 at 21:37
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

RGB_DS
  • 98
  • 4
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)