Use Swift classes in Bridging Objective C files - objective-c

I have project which is written on Swift but some part of project is written on Objective-C++ for integration with C++ library. My .mm files don't see Swift classes. I have done all steps from Can't use Swift classes inside Objective-C but still can't fix it. Auto-generated "project-Swift.h" generates with errors. I've tried to delete pieces of code in which error occurred and it worked well, but this "project-Swift.h" regenerates every time when I clean the project. Here is screenshot with errors link. Thanks.

This looks like you're not including the headers that define the missing symbols, like NSViewController, before including your bridging header.

Related

How does the Objective-C compiler behave when a Swift bridging header is imported?

I frequently work on projects that utilize both Swift and Objective-C code. I heavily depend on Swift extensions, and it isn't unusual to see multiple *Extension.swift files with hundreds of lines of code within these projects.
The problem arrises when I just need to use one or two Swift classes in Objective-C. If import ProjectName-Swift.h exposes all Swift files to Objective-C, how is the compiler linking these classes? More importantly, are my Swift extensions being linked to all Objective-C files that import the bridging header?
If I just want a single Swift Dog class within Objective-C, does this come with the penalty of including/exposing all Swift classes/struct/functions/extensions to my DogWalker.m class? Will it end up compiling down to a larger object?

What is the use of bridging header? Should we avoid using bridging header?

What is the use of bridging header?
Is it just for using Objective-C and Swift code in the same project?
Should we avoid using bridging header?
Say, if there are two third party library which are very similar; one of them is in Objective-C and other is in Swift. Should we use the Swift library or use Objective-C library. Are there any downside of using bridging headers?
Apple has written a great book that covers this in depth. It can be found here:
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html
I will quote it to answer your questions:
"What is the use of bridging header?
Is it just for using Objective-C and Swift code in the same project?"
To import a set of Objective-C files in the same app target as your Swift code, you rely on an Objective-C bridging header to expose those files to Swift. Xcode offers to create this header file when you add a Swift file to an existing Objective-C app, or an Objective-C file to an existing Swift app.
The answer to this question is yes. It is just there to make Swift and Objective-C work together in the same project.
"Should we avoid using bridging header? Say, if there are two third party library which are very similar; one of them is in Objective-C and other is in Swift. Should we use the Swift library or use Objective-C library. Are there any downside of using bridging headers?"
There are always tradeoffs. The first answer to this is no you should not avoid using a bridging header; however, as far as third party libraries you have to look at many factors. Which one has more functionality? Is it being maintained and/or added to frequently?
Using an Objective-C library will also add things to be aware of and work around. From the book:
Troubleshooting Tips and Reminders
Treat your Swift and Objective-C files as the same collection of code, and watch out for naming collisions.
If you’re working with frameworks, make sure the Defines Module (DEFINES_MODULE) build setting under Packaging is set to “Yes".
If you’re working with the Objective-C bridging header, make sure the Objective-C Bridging Header (SWIFT_OBJC_BRIDGING_HEADER) build setting under Swift Compiler - Code Generation is set to a path to the bridging header file relative to your project (for example, “MyApp/MyApp-Bridging-Header.h").
Xcode uses your product module name (PRODUCT_MODULE_NAME)—not your target name (TARGET_NAME)—when naming the Objective-C bridging header and the generated header for your Swift code. For information on product module naming, see Naming Your Product Module.
To be accessible and usable in Objective-C, a Swift class must be a descendant of an Objective-C class or it must be marked #objc.
When you bring Swift code into Objective-C, remember that Objective-C won’t be able to translate certain features that are specific to Swift. For a list, see Using Swift from Objective-C.
If you use your own Objective-C types in your Swift code, make sure to import the Objective-C headers for those types before importing the Swift generated header into the Objective-C .m file you want to use your Swift code from.
Swift declarations marked with the private modifier do not appear in the generated header. Private declarations are not exposed to Objective-C unless they are explicitly marked with #IBAction, #IBOutlet, or #objc as well.
For app targets, declarations marked with the internal modifier appear in the generated header if the app target has an Objective-C bridging header.
For framework targets, only declarations with the public modifier appear in the generated header. You can still use Swift methods and properties that are marked with the internal modifier from within the Objective-C part of your framework, as long they are declared within a class that inherits from an Objective-C class. For more information on access-level modifiers, see Access Control in The Swift Programming Language (Swift 2.2).
Que : What is the use of bridging header?
Its correct to say, Bridging header allows user to use Objective-C classes/files in their swift code in same project.
A Swift bridging header allows you to communicate with your old Objective-C classes from your Swift classes. You will need one if you plan to keep portions of your codebase in Objective-C. It should be noted that even if you decide to convert all of your code to Swift, some classes or libraries you may use such as SVProgressHUD haven’t been rewritten in Swift and you will need to use a bridging header to use them.
Que : Should we avoid using bridging header?
Considering your question there are 2 possible cases.
case 1 : Lets say your project is developed in Objective-C and now you are developing new features using swift in it, in this case you have to have BridgingHeader as you need access of your Objective-C classes in swift code.
case 2 : If your project is developed in swift then there is no need to have Bridging header, as well if its in only Objective-C and you are not planning to move it in swift then also you don't need it.
Read more about Using swift with cocoa and Objective-C in apple documentation.
Following apple document image indicates usage of Bridging header
No, there are no downsides to using Obj-c code in your Swift project. Bridging header only exposes your Obj-c files to Swift. The two languages can coexist in the same project with no problems, as you can expose your Swift code to the Obj-c just as easily too - xCode will generate a header for all of your public Swift declarations. Although everything is possible, if you start a new project you should stick to one language so the project is easier to understand. For example if you decide on Swift you should only use Obj-c for libraries that are not available in Swift.
The bridging header allows the use of Swift and Objective-C in the same project. There are no downsides to having a bridging header in your project as the two languages can work well together within the same app.
Removing a bridging header from a project after it has been added may cause errors, as it is referenced in other places in the project when it is created.
If you only intend to use one of the two languages, a bridging header is unnecessary. On the other hand, if you are using both Swift and Objective-C, a bridging header is required and will not cause any issues.
Here is a link to find more information on the subject:
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html
I hope that answered your question. Good luck with your project!
What is the use of bridging header?
You have already got that answer. You're right.
Should we avoid using bridging header?
No. Its good when a third party library developed in Obj-C and may not available in Swift yet. You should use bridging header to have a best library for your app.
It depends which on you choose. In case of networking? If your project is in Obj-C based you can use AFNetworking or with the case of Swift you can use AlamoFire, you can still use AFNetworking in Swift but its not suggestable.
Bridging headers are a great way to get Objective - C code into your Swift project. If you have two libraries, one that is in Swift and one that is in Objective - C, choose the one that will offer more functionality in your app. If they offer the same functionality, I'd just go with the Swift library -> My reasoning: if the Objective-C library isn't widely used and there aren't many tutorials on how to convert the Objective - C code into Swift, it can be very time consuming to figure it out on your own. If you use a Swift library, the code is already formatted in the correct language, saving you time and potentially money (depending on if this is a hobby for you or not). As far as any downsides to using a bridging header, their really isn't! With so many libraries written in Objective-C, you almost need a bridging header in your app. Take, for example, Reachability (Here is a video on implementation in Swift). This is a library that Apple created to handle network interruptions in your app. This is a great tool for developers and requires a bridging header. Here is a great YouTube video on how to use a bridging header, but if you add a header file into your Swift file, Xcode typically asks to crete one for you. Hope this helps!

C++ file in Swift/Objective C

i am currently developing a simple app on my own.
I want to use a library from some sample app. The library consists of .mm files (C++ code) and runs perfectly on the original project.
However, when i copy the library to my file (Objective C), it seems that my other object files do not see the file. All the classes and protocol defined in this library are not recognised at all.
Errors are such as "No type or protocol name", "Unknown typename "classname" " when i try to use the library classes and protocols.
I have spent quite a lot time searching, but to no veil.
Thanks in advance.
Objective-C simply won't understand the C++ language constructs like class, etc. If you want to use this Objective-C++ code in your app then your app also needs to become Objective-C++ which can be done simply by renaming all your source files from *.m to *.mm.
In the case of Swift, however, you cannot expose C++ to it at all, and can only integrate it with C or Objective-C, so you are therefore forced to create a pure Objective-C wrapper for the C++ code (i.e. implementation in .mm but exposing no C++ types in its header file).

module.map for accessing (Swift and Objective-C) classes in main target from test target

I am in the process of adding Swift classes to an existing Objective-C project. As part of this, I have added a MyProjectTests.swift to the target MyProjectTests. It imports Swift classes from target MyProject with import MyProject and that works just fine.
I now want to use #import Swift; in MyProjectTests.mas well. However, the compiler issues the error Module 'MyProject' not found.
I have these questions:
Make both import and #import succeed in test target
Why can it be the case that the Swift compiler sees module MyProject but the Objective-C compiler does not? What build settings in MyProjectTest do I have to change to make #import MyProject succeed as well.
Export Objective-C classes from main target
Ultimately MyProjectTest.swift and MyProjectTest.m also need access to Objective-C classes from target MyProject. So far I have multi-targetted such files, but I want to switch to using modules also here.
My current understanding is that this is a matter of providing a module.map file which would list header files for the classes I wish to "export".
What are the exact steps I have to go through? Where should I place the header file and which build settings do I need to change in the two targets MyProject and MyProjectTests?
I currently have a (so far empty) module.map inside my project and build settings for target MyProject include Defines Module: Yes, Product Module Name: MyProject.
UPDATE I am by now wondering whether it might be impossible to expose (Objective-C) files from an iOS application (instead of framework) project as a module. But then it already seems to work for Swift files (somehow).
I've by now concluded that this is not possible with current Xcode (6.1.1) tooling. (What a waste of time!)
The old scheme of bi-targeting source files to both MyProject and MyProjetTest also presents several challenges for a mixed Objective-C/Swift project with a non-trivial amount of code:
Its Objective-C part defines a legacy NS_ENUM(Integer, Repeat) which name-clashes with Swift.Repeat<T>. Referring to it as MyProject.Repeat (not MyProjectTests.Repeat) causes problems when compiling for target MyProjectTests, which changing this target's Project Name (also) to MyProject (not: MyProjectTests) does not seem to solve.
Compilation of constructs where Swift class A employs Objective-C class B, which in turn employs Swift class C does not seem to be possible in a straightforward way. Since the compiler has not yet produced MyProject-Swift.h with the definition of C, it cannot compile B. But since it cannot compile B it cannot compile A and therefore cannot produce MyProject-Swift.h. Catch 22, or so it seems.
Bi-targeted Swift code imports Swift classes from auto-generated MyProject-Swift.h. For the target MyProjectTests this name does not apply, yet that's what it is in the source files. I did not want to go down the road of changing MyProjectTests' Project Name (see above). Importing the right auto-generated file via the targets *.pch may be possible, but then it may be not ...

Using C++ namespaces in objective C

I am working on a project that requires a third party library implemented in C++. I have successfully added library to my xcode project, but the problem is that the classes in library contains namespaces and when I try to access methods via namespaces, the XCode generates an error that: "utils undeclared". "utils" is the namespace I am trying to use.
My question is that is there a way to use C++ namespaces in ObjectiveC?
The code I am using to call the method is:
utils::method();
I have tried renaming my ObjectiveC ".m" file to ".mm" file, but the problem remains the same.
We are using C++ libraries in Objective-C and have no problem using C++ namespaces. As Mustafa has indicated, you need to change the Objective-C file extension to .mm to get XCode to recognize the file as Objective-C++. Then you just need to #include (not #import) the C++ headers containing the C++ namespace declarations - this is as you would normally do for 'normal' C++.