myProjectName-Swift.h not found after clean build - ios

Spent a lot of time on finding the solution on google and SO but no success. Very hope someone can point out what can be the problem.
So I have objc+swift project. I have a Bridging Header file with imports of Objc header files that I need to use in Swift.
To explain the issue I'll share 2 scenarios. In the 1st scenario, everything works fine. In 2nd it shows an error.
Please note: Both scenarios have the same code base.
Scenario 1. Doesn't work, shows error.
I open the project.
Hard Clean it.
Build
Shows error: 'myProjectName-Swift.h' file not found
It also shows such error:
failed to emit precompiled header
'/Users/tungfam/Library/Developer/Xcode/DerivedData/myProjectName-ctxxkwqtckhvyoawavmuzmdxqaml/Build/Intermediates.noindex/PrecompiledHeaders/myProjectName-Bridging-Header-swift_1UP5PCPCLBPHP-clang_18PVO5108TD8S.pch'
for bridging header
'/Users/tungfam/Developer/myProjectName/myProjectName/App/myProjectName-Bridging-Header.h'
Scenario 2. How to make it work.
I take the same code from Scenario 1.
Hard Clean it
Comment the imports in Bridging Header file
Comment the Swift code where I used Obc files (that were declared in bridging header that I just commented in previous step)
I build the project. It succeeds.
Since some parts in the app are broken cuz I commented stuff. I uncomment the imports in Bridging Header file and the Swift code where I used Objc classes.
Run again (without hard clean) and everything works.
Will really appreciate any help on this issue. Please share anything you think that may help to fix this issue.
I'm using Xcode 10.0; Swift 4.2
UPDATE1: I think it has to do something with the 2nd error I placed above. Maybe it can't generate that bridging file.
UPDATE2: I read something like: "If you are importing the Objc file named ABC into Bridging Header. And if this ABC imports into himself the file myProjectName-Swift.h. Then this case may have some problems. Do you think it can be true?

You must not use #import "ProjectName-Swift.h" in the header files.
If you need Swift classes or protocols in the Obj-C code, you may forward declare them in the related Obj-C header. Here's more information about that:
When declarations in an Objective-C header file refer to a Swift class or protocol that comes from the same target, importing the generated header creates a cyclical reference. To avoid this, use a forward declaration of the Swift class or protocol to reference it in an Objective-C interface.
// MyObjcClass.h
#class MySwiftClass;
#protocol MySwiftProtocol;
#interface MyObjcClass : NSObject
- (MySwiftClass *)returnSwiftClassInstance;
- (id <MySwiftProtocol>)returnInstanceAdoptingSwiftProtocol;
// ...
#end
Also, please note, you may have issues with importing Swift Enums and Protocols and Classes into ObjC, so you may need to explicitly define items which you want to be available to ObjC code with #objc keyword.
And you won't be able to use Swift structs in Obj-C.

From Swift to Objective C you just have to use #import "ProjectName-Swift.h" on your Objective C classes that needs access to Swift code. There's no need to add on the bridging header file. For the other way Objective C to Swift then you need to declare in the bridging header file.

Related

How do I create an Objective-C bridging header?

I'm following this guide on adding OneSignal to React Native, and there is one section where is says:
Open NotificationService.m or NotificationService.swift and replace the whole file contents with the code below:
<provides code to add>
If you are using Swift, make sure to create a separate Objective-C Bridging Header for your OneSignalNotificationExtensionService and add the following import:
#import "RCTOneSignalExtensionService.h"
Then you need to tell your Xcode project settings what your bridging header is named, like this.
I added the code they provided to NotificationService.swift because that's the only one of the two files that exists in my project. So I assume I'm "using swift" as they put it. The problem is that when they say to create a separate Objective-C Bridging Header, I don't know how to do that. All I've been able to find online is that when you import Objective-C code into your swift project, Xcode should automatically prompt you to create a bridging header. Xcode hasn't done that for me.
Does anyone know how I can create an Objective-C bridging header?
You have to create a new objective c class:
then
then you name it and specify as objective-c class at language
then you select your directory and hit create. At this point xcode is going to ask you whether or not you want to create bridging header. Yep do it.
And at the end it should look more or less like this at your project.
hope that helps you.

How to work with Swift file in Objective-C?

I want to use one third party library which is written in Swift but I am working in Objective-C environment. How to do that? Until now what I have done is:
Drag and drop the third party library into my project.
It is asking for the bridging header I clicked on yes.
In Build settings defines Modules no to yes in both.
Product Module Name showing like $(PRODUCT_NAME:c99extidentifier). I have tried with my project name also.
Now I am getting plenty of errors like below:
pDatePicker.swift:50:9: Consecutive declarations on a line must be separated by ';'
and
Ambiguous use of 'open'.
I am getting errors around 50 to 60 same as above errors. Where is my mistake? Can anybody help me?
Are you able to see projectName-Swift.h file in your project ?
Demo Example is available on github.
https://github.com/hasyapanchasara/UsingSwiftInObjectiveC
If yes then, Hope you have imported #import "projectName-Swift.h" in Objectice C .m file ?
#import "projectName-Swift.h"
Then only you would be able to access objective c files in swift code.
Refer
https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html
Check in build setting
Objective-C Bridging Header
ProjectName-Bridging-Header.h has perfect location.
if there is problem with that path than bridging will not work properly , that why when you compile #import "projectName-Swift.h" is not getting generate.
Download
Download above sample project.
Make sure, that your swift version in settings is the same as this lib uses; if not, try to translate it by yourself, or set Use Legacy Swift Version to YES

Bridging issue when we use Objective-c properties in swift classes

I'm doing an iPad app using swift. But I have some classes which are already developed in objective-c. Now the problem is even after I'm importing objective-c class in bridging header it is showing error in swift file where I need to use objective c variables. I'm showing the project structure and bridging header's content along with the error below.
the folder structure is like
and the bridging header's content is
#import "SObjectData.h"
#import "SObjectDataSpec.h"
#import "SObjectData+internal.h"
the following is CallSObjectData.swift where i'm actually getting issue.there might be a small mistake.
If the I set
swift compiler - code generation
as follows
I'm getting the following issue.
If the I set
swift compiler - code generation
as follows
It is giving me the file doesn't exist error
Please help me finding the bug. thanks in advance.
Make sure click on project file in left pane file explorer. Target -> Build Settings -> under field Swift Compiler - Code Generation make sure your bridging file path is correct.

Include -Swift.h in the umbrella header

I have a mixed Swift and Objective-C project. To access a Swift public API in Objective-C, the API consumer currently has to import "MyModule-Swift.h". I already have a Objective-C umbrella header called "MyModule.h". But, importing "MyModule.h" is not going to work for the Swift APIs. I tried importing "MyModule-Swift.h" in the umbrella header, but it doesn't find it (I'm assuming since it is generated on the fly by Xcode).
Any suggestions so that an API consumer can always import "MyModule.h" to use public APIs written in Swift/Objective-C will be really appreciated.
====================================================================
Edit: I apologize for not taking the time to properly frame the question. I have a framework called MyModule.
I have a Objective-C class called ABUser,
#interface ABUser: NSObject
- (void)walk;
#end
I wanted to add new behavior to this class using Swift, so I defined an extension
extension ABUser {
func swiftWalk()
}
Now, say I wanted to access the swiftWalk method defined on ABUser from an Objective-C app, I would have to #import <MyModule/MyModule-Swift.h>. #import <MyModule/MyModule.h> would work if I wanted to use the walk method. This is assuming the umbrella header MyModule.h imports ABUser.h.
I always wanted the Objective-C app to #import <MyModule/MyModule.h> and never have to worry about whether an API was written in Objective-C or Swift in the framework. So, I tried importing MyModule-Swift.h in the umbrella header MyModule.h. But, my Objective-C app didn't compile if do that. Not sure, if this is because MyModule-Swift.h is generated by Xcode on the fly during the build process.
Edit 2: Added a sample project to reproduce this issue here: https://github.com/priteshshah1983/MyObjectiveCApp
The relevant code is in ViewController.m. The build will fail with the master branch. To get it work, checkout the working branch.
The reason that using #import MyModule; worked, is that "modules are a packaging together of the framework executable and it's headers" (from this SO post).
In other words, when you #import MyModule;, Objective-C automatically imports all the swift and Objective-C headers related to the module, while you cannot include the swift header from the umbrella header. I suggest you take a look at the differences between #import and #import in the linked SO answer.
It turns out that using #import MyModule; instead of #import <MyModule/Module.h> allows using walk and swiftWalk methods as expected from the Objective-C app.
I honestly don't understand the details, but I hope this helps someone else. Please feel free to explain!

Expose Swift Files to Objective-C within Framework

I have a framework with Swift and Objective-C in it. I have the statement at the top of my Objective-C class #import "MyFrameworkHeader.h" which I thought would expose my swift code to my Objective-C class however the compiler still says the symbols don't exist, how can I expose my Swift classes to my Objective-C classes within the same Framework?
Ugh, after smacking my head for a few hours then finally posting this question, within a few minutes I found the answer:
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html#//apple_ref/doc/uid/TP40014216-CH10-XID_82
Under the header: "Importing Swift into Objective-C"
To get Objective-C to register your swift code you should go into your build settings and then see/set your project name, also see if the compatibility header option is checked to yes.
after that is set just go into your file and type #import "-Swift.h". I don't think you can import individual files with swift and Objective-C, you import all of your swift files at once. It's important that you make sure all of your swift files have no errors or you will get an error about this header not being defined. You might have to build your project with no errors for the file to get generated at least once.
I think what you're looking for is a Bridging Header.
This is a file that you import your Objective-C headers into that get exposed to Swift.
There are 2 ways to make one (as far as I know):
The easiest way, in my opinion, is to add an existing Obj-C file to your swift project, or vice-versa. Xcode should ask you if you want to automatically configure a bridging header. Choose yes, and Xcode should make a file called something like 'project name'-bridging-header.h. In this file, import your files, so #import "MyFrameworkHeader.h" should do it.
Make your own empty file with File > New File (Cmd+N) > Source > Header File. Call it whatever, and import your files like in the previous one. Before it will work, you have to enter the name of your bridging header file into a field in your Project Settings (In the first option, Xcode will do it for you).

Resources