including a class from another folder in Xcode Objective-C - objective-c

I have two folders under my project: WebServices and classes.
How would I include DriverServiceService (in WebServices), in XMLViewController.h (in classes)?
I used the following with no luck:
#import <../WebServices/DriverServiceService>
#import <"WebServices/DriverServiceService">
#import <DriverServiceService>

try to import with without '<' and '>' and give the path as ../ if class is not in the root.
#import "../WebServices/DriverServiceService" worked for me.

If you want to use classes that are in a folder other than the root of your project, you can drag in or "add existing files" to your project. Make sure the "copy" option is unchecked. Now your project references those files in the project while they remain in their original location.

In some versions of Xcode, auto completion might not work. Let's assume that the classes you are going to import are named "MyClass.h" and "MyClass.m"
To import, you simply give the filename like following:
#import "MyClass.h"

oops, nevermind
just learnt to use ""

Related

Failed to import bridging header

I've read a lot of questions and answers that deal with a similar issue, but I have yet to find a solution. If anyone could shed some light, that would be wonderful.
I created a Swift project and now I want to combine it with some Objective-C. My "failed to import bridging header" only occurs when I attempt to #import my Chartboost.h file. So, as long as I don't have anything in my bridging header file, Xcode finds it and gives me no issue. But once I add this:
#import <Chartboost/Chartboost.h>
I get the error along with 38 other errors saying "Swift Compiler Error - Function definition not allowed here".
I've correctly imported my framework. And my framework search path is correct. And it's only when I import the Chartboost framework. UIKit and Foundation work fine.
Here is what I did leading up to the issue....First, I created a new Obj-C file and then clicked "Yes when Xcode gave me a pop-up asking if it could configure a bridging header. This created "FunFacts-Bridging-Header.h"
Then I made sure Objective-C Bridging Header path was correct under Swift Compiler - Code Generation.
I even put in a very specific path /Users/me/Desktop/FunFacts/FunFacts-Bridging-Header.h
and it still says "Failed to import".
I've also set Defines Module to "Yes" (because I heard that may help). And my product module name is FunFacts.
Why is FunFacts-Bridging-Header.h failing to import when I try to add #import ?
I answered this in another post: Chartboost integration issues with XCode 6.1
EXPLANATION:
It seems like some pods and libraries don't bother importing the basic frameworks as they expect your code to already have them. This doesn't work with Swift as the way to import frameworks changed.
All you need to do is to add the frameworks needed in your bridging header file.
ANSWER:
It depends on what errors the compiler throws.
If it complains about NSObject, NSString, etc... you need to add
#import <Foundation/Foundation.h> in the top of your bridging header file.
If it complains about UIView, UIButton, etc... you need to add #import <UIKit/UIKit.h> in the top of your bridging header file.
I figured out 2 solutions!
1) This isn't the prettiest way to do it, but I copy and pasted all my code from my Chartboost.h file into my Bridging-Header.h file instead of importing . This worked. But I knew there was a better way, so I kept hunting...
2) The correct solution, I believe, is what I did next. My project's (not target) Framework Search Paths was empty. So, I went ahead and added the path to the Chartboost SDK like so: /Users/me/Desktop/Apps/SDKs/Chartboost
Now it builds and runs with no problem and I didn't have to copy and paste everything into the bridging header. All that was needed was
#import <Chartboost/Chartboost.h>
If anyone is having a similar issue, just read what I did in my question, and then follow it up with this answer.
Had a nearly identical issue and found a solution that worked for me.
My problem was that the Bridging Header was not in ALL my targets.
It was in my project but not my UnitTest target. So I added it to by my UITest and UnitTest and it started working without issue.
The problem like your's puzzled me.
But I found a solution.
#import <Foundation/Foundation.h>
You should put this code (↑) before your code.
This is just my solution (↓).
#import <Foundation/Foundation.h>
#import <Chartboost/Chartboost.h>
Good luck!
This is how I solved it (and works!):
Create yourProjectName-Bridging-Header.h file at the root of your project
Include in that file the .h of the classes you want to expose and use into your swift project
Go to yourProject->Build Settings->Search Paths, and set to Yes the "Always Search User Paths" key.
Set "User Header Search Paths" to your project root path.
That's it.
Apparently, Xcode miss out on third party folders when they are copied into your project
I am on Xcode 6.3 , swift 1.2.
The answer is really very simple.
Make sure you are adding your bridging header path in SWIFT_OBJC_BRIDGING_HEADER under the target section instead of the project section.
If you use CocoaPods this could save your time.
1) The first what you need to do is to check your Podfile it will be like:
target 'YourProjTests' do
inherit! :search_paths
end
target 'YourProjUITests' do
inherit! :search_paths
end
2) Open baseproj configuration and set for test targets correct Pods-Proj.debug , see attached image:
If you have these lines in you bridging header:
#ifndef Bridging_Header_h
#define Bridging_Header_h
#endif /* Bridging_Header_h */
Just delete them, it will solve the problems of Foundation and UIKit.
One case is that if import <Chartboost+Extention/Chartboost+Extention.h> ,
The right way is to import <Chartboost**_**Extention/Chartboost+Extention.h> ,
Just because Pod build will change the framework name of Chartboost+Extention into Chartboost_Extention

Swift to Objective-C header not created in Xcode 6

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 Objective-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.
Now it works.
Project must have a Product Module Name that does not include spaces.
Defines Module must be set to Yes in Build Settings, under Packaging.
Finally works. Thanks to everyone for the help :-)
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 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 :)
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 your project module name has spaces in it, you must replace the spaces with an underscore.
For instance, if your project name is "My Project", you would use:
#import "My_Project-Swift.h"
* 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 wanted to add one more reason you might find an issue with this - I was creating a framework that mixed Swift and Objective-C code. I was not able to import the Swift classes outside the framework - I checked for the -Swift.h file and it was being generated but was empty.
The problem turned out to be very, very simple - I had not declared any of my Swift classes public! As soon as I added the public keyword to the classes, I was able to use them from classes inside and outside the framework.
Also of note, inside the framework (inside .m files only as another answer mentions) I had to import the -Swift.h file as:
#import <FrameworkName/FrameworkName-Swift.h>
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.
Allow me to share my experiences trying to use Swift in an old objc project. I did not have to set Defines module to YES.
In my case I needed to manually make sure there was an objc Bridging Header. Only the generated interface header name was present in my build settings.
This lead to a MyApp-Swift.h file to being generated, but without any traces of my Swift classes.
The Apple documentation says that you will be prompted to create a bridging header when adding your first swift file. Well, I wasn't. I manually added a MyApp-Bridging-header.h file and pointed to it in the "Objective-C Bridging Header" field. That made my MyApp-Swift.h file become populated with my Swift classes.
Docs: Importing Swift into Objective-C
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.
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
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.
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.
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.
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://stackoverflow.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.
Seconding what a lot of people have here, but adding a pertinent screen shot. Swift and Obj-C code can certainly live together. It's not an all or none game.
To access Swift files in your Objective-C, all you need to do is add this call to your Obj-C file (in the .m / implementation file):
#import "{product_module_name}-Swift.h"
(Where {product_module_name} represents the product module name of your project). Rather than try to guess your product module name or figure out corner cases with spaces and special characters, just go to the build settings tab in the project and type in "product module name" - the inspector will reveal yours to you. Mine was something I did not expect it to be. Check out this screen shot if you're confused.
And to get Obj-c code working in Swift, you just need to add a bridging header file and import the relevant Obj-C headers there.
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.
Comment out the #import "ProductModuleName-Swift.h" statement in
your Objective-C implementation file
Comment out any references in the Objective-C implementation file to
Swift Classes
Clean & Build
Resolve all errors/warnings
Remove the comment on the #import "ProductModuleName-Swift.h" statement
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)
Verify that "ProductModuleName-Swift.h" is generated by Cmd-Clicking
on the class name of the #import "ProductModuleName-Swift.h" statement
Remove the comment on the code referencing Swift classes in the Objective-C implementation file.
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.
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!
The most important thing is that This file is invisible!!! At least it is in Xcode6 beta5. There will be no such file named "YourModule-Swift.h" in your workspace. Just make sure you have module name and defines module set to yes, and use it in your Objective-C class.
You have to import a header in Objective-C classes, which is:
#import “ProductModuleName-Swift.h”
It is automatically generated, on the reference it says "Any Swift files in your target will be visible in Objective-C .m files containing this import statement."
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"
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
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 :)
I found a trick that always works on me.
Create your #import "ProductModuleName-Swift.h" in your appDelegate.h file and in your ProductName-Prefix.pch file. If you don't have it in xcode 6 you can create it with this way Why isn't ProjectName-Prefix.pch created automatically in Xcode 6?
Command+shift+k to clean your code, if you receive an error about your "ProductModuleName-Swift.h" delete it from appDelegate.h file.
Clean your code again. Now everything will work like a charm
If you receive again error about the "ProductModuleName-Swift.h", now create again in appDelegate.h file and clean your code again.
Do this work (delete and create the "ProductModuleName-Swift.h" from appDelegate.h file and clean your code) everytime you receive this error to silent it.
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
If you were able to build a project before, with no issues related to “ProductModuleName-Swift.h” not found error, and now you are getting that nasty errors again, the reason might sit in your recent changes.
For me this was by (accidental) incorrect .swift file encoding. Reverting changes and bringing the back manually, does the job.
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.
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.
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.
I had to delete WatchOS2 swift code from my Objective C project. And only after that XCode offered to generate -Swift.h
I had similar problem but my project was compiling before and suddenly got error after few files code change. It took me while to figure out why I am getting 'File not found' error for myproject-swift.h file. The code changes I had done had some errors. Xcode did not point put those error instead all time showing the 'File not found error'. Then got copy of previous version code and I compared with new code and merged file one by one. After each file merge complied the project to find the error. So bottom line is if you have error in your code Xcode may just display 'file not found error' for myproject-swift.h file. Most likely you have compilation error in your project. Clean those error and it will work.
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.
Sometimes you just need to unset and then set again the target membership on the obj-c .m file.

Getting "Duplicate Interface Definition" error, definitely has to #import ing header files

I'm helping on an iOS project with lots of methods and definitions common to many different classes in the AppDelegate. So, in each of those classes, in the .h file, I use #import "AppDelegate.h". This works fine until I need access to one of those classes that already imports the AppDelegate into another class that imports AppDelegate. At this point, I get a Duplicate Interface Definition error for AppDelegate.
Ok, so that seems fair. I'm already importing AppDelegate into a file that I'm importing, so AppDelegate is getting imported from two different places. So I remove the AppDelegate line, and everything is fine.
But what happens when I need to import two classes that both need to import AppDelegate?
I have a very specific problem that I'm trying to wrap my head around, and I know it is being caused by something that has to do with this, but I'm not sure what. So I'm hoping if I figure out how I'm supposed to be handling this sort of importing, and sort everything else out, and hope that this solves my problem. So to put this in more concrete terms:
I have ClassA.h, ClassB.h, and ClassC.h. All have #import "AppDelegate.h". When I need to use #import "ClassB.h" in ClassA, I remove the #import "AppDelegate.h" line from ClassA. Everything works smoothly. But what happens if I also need to #import "ClassC.h" into ClassA, and but ClassB and ClassC NEED to have the #import "AppDelegate.h"?
EDIT:
I tried the exact scenario I described above in a clean project, and it built fine, so there is something else at play. But what I can say with certainty is that when this issue came up previously with this project, it was a duplicate interface definition of AppDelegate, and when I removed the #import "AppDelegate.h" line, the error went away, and I still had access to the AppDelegate.h methods and enums through other imported files.
The best prevention and cure for this is to follow some guidelines on when to import from a header file. As a general rule, never import from an Objective-C header except in these cases:
You need to extend a class declared in another header.
You need to declare conformity with a protocol declared in another
header.
You need to refer to a non-class, non-protocol type defined in another header in the public methods and / or properties. To refer to protocols and classes, forward declare them with #class or #protocol, like #class ClassFromOtherHeader;
Every other #import should go in your implementation. My recommendation is to start moving all your #import statements out of headers and into the implementation files according to these rules. Start with the files you think are at the root of the problem and move outward. This will fix your problem and give you the side benefit of clearer code and faster build times.
For me none of the above answers were helping, nor did the answer given here work.
What fixed it for me was closing Xcode, going to ~/Library/Developer/Xcode/DerivedData and deleting all of the derived data associated with this project. After that I reopened the project and it was working fine.
Hope that helps someone!
In my case, none of the solutions mentioned fixed the issue. Xcode was reporting a duplicate interface for a class I rewrote in Swift. Somehow it kept pulling in the Objective-C header file for a class that wasn't directly referenced in the project.
I opened the Terminal, cd into the project directory, then ran the following to track down any files that were including the class header:
grep -nr ProblemClassName.h .
It turned out that the bridging header included an obsolete file that wasn't even referenced in the project navigator. That in turn was importing the header files referenced in the Xcode error, that were also not included in the Xcode project navigator. Now I know to not rely only on the Xcode project navigator for files referenced by the error.
tl;dr Double check the bridging header to ensure that all files that are imported there should be there and are not importing headers that are in-turn importing the problem headers.
I found that a project had a subproject and instead of referencing the includes in the subproject with the proper syntax:
#import <SubProject/Filename.h>
It was directly importing them
#import <Filename.h>
This was only possible because the path of the subproject was included in the "header search paths" of the main project - which is the wrong way to do business. So I deleted it from there.
The subproject should copy the needed included files in its "build phases - copy files" section (which was already happening actually), and the proper form of import that uses the Subproject/Filename.h syntax should be used.
Fwiw I started getting this seemingly at random - for me the fix was to do Product->Clean and it magically went away.
For me, I forgot to include parenthesis in interface definition in m file.

Organising imports using square brackets in Xcode for a framework

I have adapted the Oomph MapKit framework for use under ARC. To do this, I created a new project in Xcode and added their sources from GitHub. I also added a small test app in the same project to test the workings of the framework. I created a target for both the framework and the test app.
All seems to be working nicely however I cannot get the imports to behave properly.
In the original source files they have (as an example from the MKAnnotation.h file):
#import <Cocoa/Cocoa.h>
#import <MapKit/MKView.h>
#import <WebKit/WebKit.h>
This generates an error in my project stating that the file MapKit/MKView.h was not found and I need to replace the import with:
#import "MKView.h"
What do I need to do make the imports with the square brackets work? I've gone through the massive amounts of settings but for the life of me cannot find a clue.
You might need to add the framework in question to your project. Then it'll be on the search path for the "brokets" form.
Go to your project file (usually the top thing on the files listing to the left, choose your application target, usually the top thing in Targets, select Build Phases, open up "Link Binary With Libraries", and add the framework there.
Why not just #import <MapKit/MapKit.h> so you have access to all of the header files contained in the MapKit framework?

Objective-C's #import statement - Won't Import a file inside a folder

I'm new to Objective-C here, and still learning its syntax, so I'm experimenting some things... and I'm trying to understand how the #import statement works when it comes to importing a file inside a folder.
I have a main function inside of a file and in the same directory of my main function contains a folder for a class, inside that folder I am trying to import a header file for that class.
I'm trying to import it like this:
#import "Person/person.h"
And I believe that should work but instead Xcode fires off a error saying it can not find the file/directory.
The folder that contains person.h is in the same directory as my main function's file.
I still don't understand what's wrong with that piece of code, if someone can tell me the proper way to do this it would help a lot, thanks!
Try #import "person.h", the folder isn't really. It is a group, something like a virtual folder in the project, that let you organize visually your project files.
(one way) to use this functionality is to add the parent directory (of Person/) to your target's include paths.