swiftobjective-cxcodemacrosbridging-header

When importing a header into swift file, how do I define conditional macros for different targets?


I'm trying to import a Swift class into an Objective-C file in Xcode. It works fine, based on exposing the class to Objective-C and importing the ProductModuleName-Swift.h Xcode generated file. The problem I'm having is that my app has multiple targets, and it seems that Xcode generates a different -Swift.h file for each target. So if I import the production -Swift.h, the dev target won't build, and vice versa.

I've tried:

- Importing both of them: doesn't work (neither will build due to not being able to locate the other)

- Added conditional macros to only import the right file for the right target: when wrapped in the conditionals the Swift methods from the class are no longer locatable by Xcode and don't compile.

My current solution, which does work, involves going into build settings for one of the targets and disconnecting the Generated Header Name from the Product Module Name, and manually giving it the same name as the other target. Now it compiles fine. However my concern is that I'm tinkering with something that shouldn't be changed and could have negative ramifications.

So my question is - is there a better way of doing what I want to achieve? Thanks in advance.

*LogStatements Swift class no longer found and doesn't compile ->

 #if PRODUCTION
#import "ProductionTarget-Swift.h"
#elif DEV #import "DevelopmentTarget-Swift.h"
#endif

@implementation STNetworkManager

+ (void)saveDictionary:(NSDictionary *)dictionary withFileName:(NSString *)fileName {

if (dictionary == nil || fileName == nil) {
return;
}
// check if all objects are valid JSON objects

if (![NSJSONSerialization isValidJSONObject:dictionary]) {
NSLog(@"Error saving dictionary, invalid JSON object: %@", dictionary);
LogStatements *logging = [[LogStatements alloc] init]; [logging logger:@[@"Hello from Objective-C"]];
return;
}

Solution

  • The Swift compiler generates one header for each module. Your different targets are creating different modules and so the header ends up with different names.

    The name of the header generated by a target is in the build settings for that target. It's in the section Swift Compiler - General and the setting name is Generated Header Name.

    If you set that generated header to the same name for each of your targets that may resolve your issue.

    If both targets are building the same "thing" - the same Module, you might also look in the Packaging Section of your target build settings and change the targets so that they use the same Product Module Name.

    Generally, however, if you want to build the same "thing" for debug and for release, what you would do is set up one single Target and then you can build it for debug, or for release using the product menu. If you need to make more complex changes then you can make different Schemes of the same target to switch between debug and release. The current scheme is at the left side of the small information area in the tile bar of an Xcode project (see the image at https://developer.apple.com/documentation/xcode/build-system where the scheme and target settings are called out).