How to work with Swift file in Objective-C? - ios

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

Related

myProjectName-Swift.h not found after clean build

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.

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.

Cocoa pods objective c files in Swift project. Bridging issue

I downloaded code from here:
https://github.com/QuickBlox/quickblox-ios-sdk
wich include sample-chat-swift example folder where seems somehow guys created a framework.
In my case if I just use cocoa pods to pull code into my project Xcode says to me that we can't find any of downloaded classes. So I am sure that is problem with bridging but my question what are the steps I need to do to create framework like guys did in theirs example.
Or do I need to bridge each files manually? If so I guess it can take so much time.
I created my own framework for using Tumblr in an app. I'm sure you know how to setup a framework project, but I'll explain what I did when I complied the framework. After you finished the framework what you do is under your xcode project folder in the directory is a fold Products. The text for Project.framework should be red or black. Either way run your project and make sure its black. Then right click and choose Show in Finder. Then you can copy that framework and bring it into the top of the project you want to use the framework in.
You will also need to make a header file. Like the one I have below if you are using Obj-c, but I'm sure you can google and find an example in swift it you are trying to hide certain aspects of your framework with a swift interface file.
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
//! Project version number for Tumblr.
FOUNDATION_EXPORT double TumblrVersionNumber;
//! Project version string for Tumblr.
FOUNDATION_EXPORT const unsigned char TumblrVersionString[];
// In this header, you should import all the public headers of your framework using statements
//#import <Tumblr/Tumblr.h>
#import "TMSDKUserAgent.h"
#import "JXHTTPDataBody.h"
#import "JXHTTPOperationQueueDelegate.h"
#import "TMTumblrAuthenticator.h"
...
Regarding bridging issue, guys form QB answered on it:
so using this http://quickblox.com/developers/IOS-how-to-connect-Quickblox-framework#Additional_steps_for_Swift_using_CocoaPods
we can simple achieve bridging, even without creating framework.

Cannot call swift function in Objective C class [duplicate]

I have a project that was started in Objective-C, and I am trying to import some Swift code into the same class files that I have previously written Objective-C in.
I have consulted the Apple docs on using Swift and Objective-C in the same project, as well as SO question like this, but still no avail: I continue to get the file not found error after putting in #import "NewTestApp-Swift.h" (NewTestApp is the name of the Product and module).
Here is what I have done so far:
In Define Modules, selected YES for the app.
Ensured that the Product Module name did not have any space in it (see screenshot below question)
I have tried using #import "NewTestApp-Swift.h" inside ViewController.m, ViewController.h and AppDelegate.m but none of them has worked.
What else am I doing incorrectly? Thanks for your help.
Screenshot of settings:
Errors that I am presently encountering:
I was running into the same issue and couldn't get my project to import swift into obj-c classes. Using Xcode 6, (should work for Xcode 6+) and was able to do it in this way....
Any class that you need to access in the .h file needs to be a forward declaration like this
#class MySwiftClass;
In the .m file ONLY, if the code is in the same project (module) then you need to import it with
#import "ProductModuleName-Swift.h"
Link to the apple documentation about it
https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/importing_swift_into_objective-c
If the Swift code is inside a Module (like in your case):
#import <ProductName/ProductModuleName-Swift.h>
If the Swift code is inside the project (mixed Swift and ObjC):
#import <ProductModuleName-Swift.h>
In your case, you have to add this line in the *.m file:
#import <NewTestApp/NewTestApp-Swift.h>
IMPORTANT: look at the "<" in the import statement
https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html
How I managed to import swift into objective-c:
Defines Module set to YES (on project - not on target)
Product Module Name set (on target - not on project)
In your ViewController.m import the swift code with:
#import "MyProductModuleName-Swift.h"
Add a swift file to your objective-c project (File -> New -> Swift) and Xcode will create the bridging header from objective-c to Swift but this is crucial for making it work the other way around too - apparently.
For the last piece in this puzzle thanks to Swiftoverload for making me aware of actually adding a Swift file via Xcode GUI and not just dragging and dropping existing swift-files into my project for making it work:
http://nikolakirev.com/blog/using-swift-in-objective-c-project
Using Xcode 8.2.1 and if you look at Project > Build Settings > Objective-C Generated Interface Header Name, there it shows only one header file named like Product-Swift.h
This means that instead of importing each modules separately from Objective-C .m file, using individual -Swift.h file, you just import one Product-Swift.h which aggregated all Swift modules.
I encountered the same problem by looking for traditional way of importing modules separately, but the current version of Xcode and Swift 3 changed it to use only one header for all module importing.
Spent an hour on this issue, following these steps will help you to understand what's missing:
Open Xcode preference and navigate to DerivedData folder
Search for "swift.h" in finder
If you can not find any project-swift.h file, this file haven't been generated. You usually need to add #objc to one of your swift class and successfully build the app, only then will Xcode generate this file
If you found "xxx-swift.h" file, make sure your import statement contains the correct name.
I was having problems importing Swift into an Objective-C project. In the end I looked into the Derivied Data folder to check what Xcode 7 was generating. The filename was completely different to the one I was expecting.
Once I had the actual filename I imported that and the project could build.
iOS - Swift.h file not found
[Mixing Objective-C and Swift]
<name>-Swift.h should be created by Xcode automatically if Swift code expose an API via #objc or #objcMembers[About]
Usually a location looks like
~/Library/Developer/Xcode/DerivedData/
ProductModuleName-foo/
Build/
Intermediates.noindex/
ProductModuleName.build/
Debug-iphoneos/
ProductModuleName.build/
DerivedSources/
ProductModuleName-Swift.h
It can be changed by
Project editor -> select a target -> Build Settings -> Per-configuration Intermediate Build Files Path
By default the value is $(PROJECT_TEMP_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
Importing the header file, i.e.
#import "<ProjectName>-Swift.h"
within the .h file generated an error, stating:
-Swift.h' file not found
and the build failed.
Instead use:
#import "<ProjectName>-Swift.h"
within the .m file, and even though the same error appears, running the project anyway suppresses the error.
The swift classes are then available within the .m file.
If Your App name have any special character then use _ for special character.
For Example if your App name is Name "Test App®"
Then you can import swift file by "Test_App_-Swift.h".
Space and ® is replace by _ while you are import.
Make sure your swift class has the public declaration, and extends NSObject:
public class MySwiftClass: NSObject {
//...
}
The import should work with quotes, not brackets, if the swift class is in the same project.
if you add a Swift File first, rememeber to add swift file to your target..., in the left column
Had faced the same problem with my team when was working on project using git. One developer hasn't updated Xcode to the last version (7.3) which was required for latest Swift 2.2 version. So, compiler hasn't recognized new Swift syntax and couldn't generate interface for Swift library (projectname-swift.h).
Check if Xcode version is the latest one!
DEFINE MODULES: YES
and import "ProjectName-Swift.h" in .m file of Obj-C class
This worked for me to access Swift classes in Obj-c.
I had the same problem with #import "myProj-Swift.h" not found, Xcode 12.3, the year is 2021.
It appears that unless a bridging header has been generated, it is not possible to import myProj-Swift.h.
My (reproducible) solution, when needing to add Swift to objective-C projects is to create (File - New File - Swift file) a dummy empty Swift file in my project. Xcode then asks whether to create a bridging header, to which I answer yes. This causes a "myProj-Bridging-Header.h" file to be added to my project, which is visible in the Project Navigator.
Once this is done, the error on #import "myProj-Swift.h" disappears.
After that I can delete the dummy file, and insert the needed Swift classes into the project.
The logic of generating a visible bridging header, but leaving the -Swift.h entirely invisible escapes me entirely. Never mind the challenge of trying to find out about this in the official documentation Importing Swift into Objective-C, which (to me inaccurately) states "You don’t need to do anything special to create the generated header".
It is probably a good idea to also mind the answer from #Sandeep Bhandari to this question - who says the -Swift.h file will only be generated if the project compiles successfully.
More info also in this and this question.
I ran into this problem after duplicating an existing target. When I tried to build with the duplicated target, the "ProductName-Swift.h file not found" error appears.
After going through the build settings in the new target, I found the value of the setting "Product Name" somehow is set as the same as the target name. After setting it with the correct one the error disappeared.
If your product name is TestApp-Dev then filename will TestApp_Dev-Swift.h
You can verify by going to the following location
~/Library/Developer/Xcode/DerivedData//Build/Intermediates.noindex/yourProjectbuild/Debug-iphonesimulator/MashreqMobileApp.build/DerivedSources
If you want same file name for each build schemes then go to
Build Settings to be the same across your modules/schemes. (set it to $(PROJECT_NAME)-Swift.h).
If project name is TestApp, then the file generated will TestApp-Swift.h and it will remain same across the schemes
During development, there might be a possibility that you would have any swift class that is not completely implemented due to which there might be some syntax errors.
The swift header file will be available for use only if all the swift files are error free.
Make sure there are no syntax errors in the swift files and then try to import the swift header in the objective - c file
I faced the problem with the name of project (target). It included symbol "-". So the decision was next: if name of project is "Test-App", then name of imported class is "Test_App-Swift.h"
If you have multiple target make sure that you have build all frameworks
Xcode 11
I ran into this problem when building on Xcode 11. Took me a bit to figure out what was wrong, but essentially, I had changed the "Display Name" setting on the Target's "General" tab instead of changing directly in the Info.plist file through the "Info" tab on the Target.
This resulted in Xcode 11.5 going through an rewriting/creating a bunch of brand new custom build settings and modifying the name of the app module and the built .app product. In this case the new display name also had a forward slash (/) character in it which may ultimately be why it wasn't building (see #Silversky Technology's answer).
Regardless, I resolved this by undoing all of Xcode 11.5's automatic changes to the project file and manually making the same change to the bundle display name in the Info.plist file and everything works perfectly.
I wish it would tell you that it was doing stuff like this before it just up and does it without your consent.
Target executable was missing a dependency on my (or any other in fact) framework.
Build Phases -> Dependencies must list the dependencies of a target to avoid intermittent errors: in my case debug
build was fine and automated Jenkins CI builds were failing.
A nightmare to debug considering Jenkins output produces
voluminous garbage that's a huge time pit to get through.

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