objective-c - with - xcode use objective c in swift




Swift to Objective-C header not created in Xcode 6 (20)

* The only important thing is: *

to use the defined "Product Module Name" in the target, followed by -Swift.h

#import <Product Module Name>-Swift.h

// in each ObjectiveC .m file having to use swift classes
// no matter in which swift files these classes sit.

No matter if "Defines Module" param is set to Yes or No or if "Product Module Name" Project is not set.

Reminder: Swift classes must deriving from NSObject or been tagged with @objc attribute in order to be exposed to ObjectiveC / Foundation || Cocoa ...

I have recently been working to add Swift to an existing project, to get to try it out in a real-world fashion.

Upon adding a Swift source file to the project, I have no problems about getting the "Bridging Header", that is, Objective-C to Swift.

But the -Swift.h header file that is supposed to expose Swift classes either marked @objc or subclasses of ObjC classes, is nowhere to be found :-(

I don't see any specific instructions on how to accomplish the usage of my new subclass, written in Swift, in my main app code (which is still Obj-C).

The app that I am lead developer of has a fairly large codebase (70.000 lines), so transitioning it in one go is out of the question.


An actual file in the project is not created ([ProductModuleName]-Swift.h). Cmd + Click on the import either generates it on-the-fly (and in-memory) so you can see how the linkage is done, or opens a file somewhere in some Xcode cache dir, but it's not in the project dir.

You need to set Defines Module project prop (in target's Build Settings) to Yes and if your module name has spaces or dashes - use _ in all imports of the [ProductModuleName]-Swift.h file.

You can import it in all .h and .m files where you use swift types or you can import it in the .pch.

So if my Module (project) is named "Test Project", I would import it like this, in the .pch file of my project (just there):

#import "Test_Project-Swift.h"

Here is another variation of the moduleName-Swift.h not being generated.

I decided to include IOS Charts in my project but did not want to mingle the sources in the same directory, so I placed the Charts Project folder next to my code's project folder. I dragged the Charts project into my Project's Navigator Bar and included the framework in the my project target's Embedded Binaries list in the General project settings and set the Embedded Content Contains Swift Code switch to yes in my project's Build Settings tab in the Build Options section.

My project's moduleName-Swift.h file would never generate no matter what other switches or settings suggested here. Finally, using Lou Z's method of seeking out the -Swift.h files, I saw that a Charts-Swift.h file was being generated deep in my project's xcode Build directory in Charts.framework/Headers/

The solution to using Daniel Gindi's ios-charts Swift package without including the code in my project's source directory was to add:

#import "Charts/Charts-Swift.h"

To the modules charting my project's data.


I Found this solution

  • Create SwiftBridge.h
  • put #import “ProductModuleName-Swift.h”
  • Make this .h file public (important) Select the file -> In Show the file Inspector (right bar) -> Make it public

Now you can

#import "SwiftBridge.h"

instead of ProductModuleName-Swift.h

This's a workaround solution, for the next version of Xcode I think this problem will be solved. Good luck


I found that I had to fix all build errors before it would generate the file.

The problem for me was that it was a chicken/egg problem, in that I didn't see any build errors until I'd actually commented out the #import statement:

//#import "ProductModuleName-Swift.h"

which revealed a bunch of other errors in my Swift code.

Once I fixed these new errors and got the source building successfully, I uncommented out the #import and bingo! The header was created and importing correctly :)


I had a similar problem and found that you can only add

#import “ProductModuleName-Swift.h”

to obj-c .m files, not .h files for the umbrella header to be found


I had the same problem. Seems like you have to adjust the settings (Defines Module and Product Module Name) before you add your first Swift file.

If you do it afterwards the "*-Swift.h" file will not be generated for this project even if you add further Swift files or delete the Swift file and create a new one.


I had to delete WatchOS2 swift code from my Objective C project. And only after that XCode offered to generate -Swift.h


I was having a hard time determining my module name/objective-c's import of swift's headers. I did read a lot of articles here too.

But the definitive answer for your project name with all its included special characters (be it '.' or a numeric or a space) - you can find the text that will work for you in the "Product Module Name" under the target's Build Settings.

For example my target name started with a numeric - "1mg" and the field mentioned above showed "_mg" as my module name.

so I used #import "_mg-Swift.h" and it worked.


If XCode is actually generating your -Swift.h header (deep inside DerivedData) but it doesn't refer to your Swift classes, make sure you also have a bridging header defined. The way I read the docs implied I only needed that for calling Objective-C from Swift, but it seems to be necessary for calling Swift from Objective-C too.

See my answer: https://.com/a/27972946/337392

EDIT: It is because of public vs. internal access modifiers, as I eventually found explained in the Apple docs:-

By default, the generated header contains interfaces for Swift declarations marked with the public modifier. It also contains those marked with the internal modifier if your app target has an Objective-C bridging header.


If you're like me you've probably got the header name wrong. After bashing my head for a while I looked for the file in DerivedData and sure enough it's there. On my setup (using the standard derived data folder, I believe):

cd ~/Library/Developer/Xcode/DerivedData
find * -iname '*Swift.h'

Will find it. If nothing in that folder matches then Xcode is not generating it.

I'm using Xcode Version 6.2 (6C86e)


If you're using something like Cocoapods (and working out of the workspace rather than the project) try opening the project and building it before opening the workspace and building. YMMV.


In my case I had to set the deployment target to at least “OS X 10.9” and the -Swift.h header was automatically generated. Keep in mind that you can get a lot of deprecation warnings when you change the deployment target version, especially when you have an older and very large Objective C code base. In our case we also had a lot of work to do in XIB files & view classes.


Just a heads up for anyone who used "." in there project name. Xcode will replace the "." with an underscore "_" for the Swift version of the bridging header file. Oddly enough the Bridging-Header.h that is generated does not replace the periods with underscores.

For example a project with the name My.Project would have the following Bridging Header file names.

Bridging-Header.h (Autogenerated)

My.Project-Bridging-Header.h

Swift.h

My_Project.h

I hope this helps anyone who used a period and was stuck like I was. This file can be found at the following location.

Macintosh HD/Users/user/Library/Developer/Xcode/DerivedData/My.Project-fntdulwpbhbbzdbyrkhanemcrfil/Build/Intermediates/My.Project.build/Debug-iphonesimulator/My.Project.build/DerivedSources

Take care,

Jon


Ok, here are all the things you really need!

1.Remove all the swift files you have added, and compile the code, without any errors.

----------

----------

2.Go to the "Projects" build settings, and set the product module name. Project must have a Product Module Name that does not include spaces.

----------

----------

3.Defines Module must be set to Yes in Build Settings, under Packaging, in your project, and not target!

----------

----------

4.Now create a swift file or a view controller, in file-> newFile->

----------

----------

It will ask to create a bridging-header, allow it to make one. If you have declined it once, you will have to manually add a -Bridging-Header.h

5.Add @objc in the controller, to tell the compiler that there is some swift file, which needs to be exposed to ObjectiveC

----------

----------

6.Build the project and import #import "-Swift.h" in any of the objectiveC controller, and it will work! You can Command-click on it to see the actual file!

----------

----------

Hope this helps!


Project must have a Module Name not including spaces. Defines Module must be set to Yes in Build Settings, under Packaging. commented out the #import statement:

If still you are having error in importing "ProductModuleName-Swift.h" then

//#import "ProductModuleName-Swift.h"

which revealed a bunch of other errors in my Swift code.

Once I fixed these new errors and got the source building successfully, I uncommented out the #import and bingo! The header was created and importing correctly :)


Sometimes you just need to unset and then set again the target membership on the obj-c .m file.


The file name is always preceded by your Target name. It is referred as Product name but practically it is the target name. So if you want it to build for a new target be ready to expect that_target-Swift.h file.

One way to handle this is

  1. Add a preprocessor for each of your target that is the name of your target itself (without spaces). Ex. MY_TARGET=1. Add this in Project settings->Build Settings->Preprocessor Macros for each of your targets.
  2. If you are using a PCH file,

Add these lines in the PCH file

#if MY_TARGET==1
#include "My_Target-Swift.h"
#elif THAT_TARGET==1
#include "That_Target-Swift.h" 
#endif

Advantage of using PCH file is that you don't have to include the headers everywhere.

  1. If you are not using a PCH file, just add these same lines in a single header and include that header wherever you need to use the swift classes.

This should work just fine.


This answer addresses the use-case where you may already have some Objective-C code that calls Swift classes and then you start receiving this error.

How To Fix Issue

The following steps ultimately resolved all of the issues for me. I read above someone mentioning the "chicken and the egg" and it is exactly that concept which led me to this procedure. This explicit process shows that one has to remove any Objective-C code referencing Swift classes until after the header is generated.

  1. Comment out the #import "ProductModuleName-Swift.h" statement in your Objective-C implementation file
  2. Comment out any references in the Objective-C implementation file to Swift Classes
  3. Clean & Build
  4. Resolve all errors/warnings
  5. Remove the comment on the #import "ProductModuleName-Swift.h" statement
  6. Clean & build (successfully or fix any remaining errors, verify that you are not referencing any Swift classes in Objective-C at this point. If so temporarily comment these out)
  7. Verify that "ProductModuleName-Swift.h" is generated by Cmd-Clicking on the class name of the #import "ProductModuleName-Swift.h" statement
  8. Remove the comment on the code referencing Swift classes in the Objective-C implementation file.
  9. Clean & Build as normal (the "ProductModuleName-Swift.h" should be generated and your Objective-C code referencing Swift Classes can be used as normal)

Nota Bene: The answers about changing spaces to underscores and the Defines Module to YES as given above still applies when performing this process, as do the rules specified in the Apple Documentation.

Bridging Header Path

In one error, the file ProductModuleName-Bridging-Header.h was not being found during the build process. This fact generated an error

< unknown>:0: error: bridging header '/Users/Shared/Working/abc/abc-Bridging-Header.h' does not exist

Closer inspection of the error indicated that the file would never exist at the location described because it was actually located at (a wrong path)

'/Users/Shared/Working/abc/abc/abc-Bridging-Header.h'. a quick search of the target/projects build settings to make the correction manually and the abc-Swift.h file was again auto generated.


This may be an obvious point (maybe too obvious), but you must have at least one swift file in the project for the header to generate. If you are writing boilerplate or config code with the intention of writing swift later the import won't work.





swift