I want to start using Swift in my Objective-C project. So i added a swift class:
import Foundation
#objc class System : NSObject {
#objc func printSome() {
println("Print line System");
}
}
And imported it into a .m file:
#import "MyProjectName-Swift.h"
When building my project i get the following error:
Bridging header 'PathToMyProject/MyProjectName-Bridging-Header.h' does not exist
NOTE: Under "Build Settings->Swift Compiler - Code Generation->Objective-C Briding Header" is set to MyProjectName-Bridging-Header.h
What should i do to solve this issue?
Any help is much appreciated.
EDIT: Bridging-Header file:
#if defined(__has_include) && __has_include()
# include
#endif
#include <objc/NSObject.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#if defined(__has_include) && __has_include(<uchar.h>)
# include <uchar.h>
#elif __cplusplus < 201103L
typedef uint_least16_t char16_t;
typedef uint_least32_t char32_t;
#endif
#if !defined(SWIFT_PASTE)
# define SWIFT_PASTE_HELPER(x, y) x##y
# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y)
#endif
#if !defined(SWIFT_METATYPE)
# define SWIFT_METATYPE(X) Class
#endif
#if defined(__has_attribute) && __has_attribute(objc_runtime_name)
# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X)))
#else
# define SWIFT_RUNTIME_NAME(X)
#endif
#if !defined(SWIFT_CLASS_EXTRA)
# define SWIFT_CLASS_EXTRA
#endif
#if !defined(SWIFT_PROTOCOL_EXTRA)
# define SWIFT_PROTOCOL_EXTRA
#endif
#if !defined(SWIFT_CLASS)
# if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted)
# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA
# else
# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# endif
#endif
#if !defined(SWIFT_PROTOCOL)
# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
#endif
#if !defined(SWIFT_EXTENSION)
# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__)
#endif
#if !defined(OBJC_DESIGNATED_INITIALIZER)
# if defined(__has_attribute) && __has_attribute(objc_designated_initializer)
# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
# else
# define OBJC_DESIGNATED_INITIALIZER
# endif
#endif
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch"
#if defined(__has_feature) && __has_feature(modules)
#endif
#pragma clang diagnostic pop
If the bridging file is created at the same level as the other classes, you might need to add the relative path, as these pictures show. Note here that the bridging file is created at the same level as the other classes:
I have the name entered correctly in the Build Settings,
but the compiler doesn't find the file.
Therefore, if I add the relative path from the root of the project (that is, I add ./ProjectName/BridgerFileName.h),
now it compiles and I can call a method in my Objective C class:
I found that after creating the bridging header file manually and choosing the default name and location, the bridging header will be placed in the project directory, which is under the root directory.
This requires the following value for the setting: Targets > [Your App Target] > Build Settings > Swift Compiler - Code Generation > Objective-C Bridging Header:
$(SRCROOT)/$(PROJECT_NAME)/$(PROJECT_NAME)-Bridging-Header.h
Note that if your project is a swift module (framework) then, as pointed out in the comments, you might prefer:
$(SRCROOT)/$(PROJECT_NAME)/$(SWIFT_MODULE_NAME)-Bridging-Header.h
For those who are removing the Bridging Header
I was going the opposite way as most of the other answers here. I had been using a Bridging Header previously, but I didn't need it anymore. After I deleted it from my project I started getting the error mentioned in the question. I performed the following steps to solve my problem.
Go to Targets > [Your App Target] > Build Settings > Swift Compiler - General > Objective-C Bridging Header and delete the path. (Thanks to #Donamite for the idea.) (You can just start typing "bridging" into the search box to find it.)
Delete the derived date. Go to Xcode > Preferences > Locations and click the gray arrow by the Derived Data folder. Then delete your project folder.
In Swift 4.1
your project you don't have bridging-Header.h file, but your project has that path. For this you need to delete that path...
Go to targets file and select Build Settings, ---->Swift Compiler - General, and delete the bridging-Header.h. Follow below screen shots....
Delete the bridging-Header.h file in Swift Compiler - General
Now you got like this...
These are steps to create Bridging header.
File->New->iOS->Header File, Give the bridging file name as like "yourProjectName-Bridging-Header.h"
Build-Settings->Objective-C Bridging Header, Just give the bridging header file name be like "ProjectName-Bridging-Header.h"
NOTE: Bridging header file should be located in the main root folder of the project where the ".xcodeproj" file located. If not move the Bridging header file to the root folder of the project. This way Xcode able to access the bridge file.
Build the project, and import necessary files in Bridging header.
To add Bridge File in Swift project.
Step 1. Go to File > Add Cocoa with Objective-C File (For temporary Purpose)
Step 2. Then the following pop up will appear
Now press Create Bridging Header Button
DONE
YOU WILL GET BRIGDE FILE IN BUNDLE
THANKS
For me it helped to use $(SRCROOT)/$(PROJECT_NAME)/ in front of my bridging header file path
For me it helped to use $(SRCROOT) in front of my Objective-C bridging header path.
$(SRCROOT)/swiftLibraries/swiftLibraries-Bridging-Header.h
Follow the steps below:
Delete bridging header file . . . (Maybe you create manually) and;
Create new Swift file in Objective-C Project . . . (Not import, first create it)
Maybe these two things will help solve your problem.
The following worked for me:
Bridging header file should be located in the main root folder of the project where the ".xcodeproj" file located. Move to project directory and drag and drop bridging header to root if it is inside any other folder.
Correct spelling mistakes in header name.
Clear Derived data
Target -> Build Settings -> Swift Compiler : General -> Add Obj C Header name.
Clean and run again.
Creating Bridging Header File Manually
First of all delete the Bridging header file which Xcode is created. And Select your project goto > Build Settings > Search the keyword. Swift Compiler - Code Generation. Click on Objective-C Bridging Header , delete that path. Now clean your Project.
Now select your project > Window in the navigation bar . Select Projects and delete your derived data from there.
Now create a new file , select the Source and then select the Header File and create your Bridging header file . File name must be your projectname-Bridging-Header.h and then create it
Select your project goto > Build Settings > Search the keyword. Swift Compiler - Code Generation. Click on Objective-C Bridging Header and now add the path in this Objective-C Bridging Header like projectname-Bridging-Header.h
Now import your classes into bridging header file and you can compile it your code easily.
Your bridging header file looks like this when you are creating your file manually.
What helped me was to move the file manually to the path mentioned in an error message. So:
I deleted the file (moved to trash)
Moved it from trash to the path in an error message
Later I also had to clean the project
Related
Hi i want create one Common SDK for 3 Project which have same functionality in it but for creating that SDK we need to use some of the pod and bridging header file
we faced issue with how to configure that SDK with pod and bridging header which is used in all 3 apps to work on
Please help me how can we achieve this.
i have tried to add pod with bridging header but some how pod and bridging header not working
You can create framework project with pods and third-party library.
Note: You can't use bridging headers within a framework.
There are 2 Solution.
1. umbrella header
2. module map
Solution 1 (umbrella header):
To include the required Obj-C header you need to set it as Public: select it in the project explorer (left pane) and change the property Target Membership (left—Inspectors—pane) from Project to Public.
[Target Membership Public]
https://i.stack.imgur.com/P26rx.png
Open umbrella header (.h) and import the required header as:
[Import Headers in umbrella header]
https://i.stack.imgur.com/WEsLG.png)
This effectively makes this header public and available to both your own framework and anyone who uses it.
Note: If you import the header as a local file, i.e. in quotes, e.g. #import "objc-header.h", you likely to hit the compiler error telling you are trying to include a non-modular header.
Solution 2 (module map):
Create a file named module.modulemap in the root of your project with the following contents:
[module.modulemap]
framework module FrameworkName {
umbrella header "FrameworkName.h"
header "objc-header.h"
export *
module * { export * }
}
In case you want to keep the definitions from objc-header.h private from the users of your framework you can add private qualifier like so:
// ...
private header "objc-header.h"
// ...
In Build Setting set Module Map File to module.modulemap
Clean the build directory (⇧⌘K) and build the project (⌘B)
I have a project that requires a local framework.
The project has the frameworks set up in a frameworks folder.
The new local framework is placed in it as well. The result folder structure is like that:
project
-- frameworks
---- theFramework.framework
------Headers
--------TheFramework.h
--------file1.h
--------file2.h
--------subfolder
----------Subfolder.h
----------Another.h
In the Bridging header the TheFramework.h and the Subfolder.h need to be imported.
It looks like that:
#ifndef Bridging_Header_h
#define Bridging_Header_h
#import <TheFramework/TheFramework.h> //This one is working just fine
#import <subfolder/Subfolder.h> //This one fails with File not found
#endif /* Bridging_Header_h */
If I change #import <subfolder/Subfolder.h> to #import <TheFramework/subfolder/Subfolder.h> then it seems that the file is found because then it fails in Subfolder.h where it tries to do #import <subfolder/Another.h> and fails again with a Not found
If I change subfolder/Another.h to TheFramework/subfolder/Another.h then it works here as well.
Now in my real life scenario I have 4 header files in different subfolders all importing around 50 other files so changing all of the imports will be... annoying.
Also if later we want to update to a newer version of the framework, all the changed imports will be lost.
Does someone know how I can solve that issue? Either by having the project find the imports as already defined or by for example defining a value somewhere that makes the compiler understand that subfolder/file.h equals to TheFramework/subfolder/file.h ?
Thank you!
Found the solution I had to add
"$(SRCROOT)/frameworks/theFramework.framework/Headers"
to my targets User Header Search Paths (Target -> Build Settings -> User header search paths.
This seems to let the compiler know where additionally search for header files including subfolders.
I'm including a Swift source in my CocoaPods library for the first time. For me to get the project to compile, I need to import the generated Swift header into my Objective-C source. This takes two different forms, depending on whether the project is being built as a static library or a dynamic framework:
#ifdef BUILT_AS_FRAMEWORK
#import <UnzipKit/UnzipKit-Swift.h>
#else
// Used when built as a static library
#import "UnzipKit-Swift.h"
#endif
I'm defining BUILT_AS_FRAMEWORK in my Xcode project for development time, but when I lint the library as a dynamic framework, and because I haven't defined that flag in the Podspec, it attempts to resolve the second import, and can't find it.
Is there a way I can define the BUILT_AS_FRAMEWORK preprocessor macro, but only if the consuming Podfile doesn't build it as a static library?
I created issue #9101 in the CocoaPods project for this question.
I was able to use an Xcode environment variable (PACKAGE_TYPE) in conjunction with a pre-compilation Run Script build phase to dynamically produce a header to import, which in turn makes the correct generated Swift Header import.
generate-swift-import-header.sh
#!/bin/sh
[[ "${PACKAGE_TYPE}" = "com.apple.package-type.wrapper.framework" ]] \
&& SWIFTIMPORT="<${PRODUCT_MODULE_NAME}/${PRODUCT_MODULE_NAME}-Swift.h>" \
|| SWIFTIMPORT="\"${PRODUCT_MODULE_NAME}-Swift.h\""
if [ -z "$PODS_TARGET_SRCROOT" ]; then
PODS_TARGET_SRCROOT=${SOURCE_ROOT}
echo "Building in Xcode instead of CocoaPods. Overriding PODS_TARGET_SRCROOT with SOURCE_ROOT"
fi
_Import_text="
#ifndef GeneratedSwiftImport_h
#define GeneratedSwiftImport_h
#import ${SWIFTIMPORT}
#endif /* GeneratedSwiftImport_h */
"
echo "$_Import_text" > ${PODS_TARGET_SRCROOT}/Source/GeneratedSwiftImport.h
Podspec update
s.script_phases = { :name => "Generate UnzipKit Swift Header",
:script => "\"${PODS_TARGET_SRCROOT}\"/Scripts/generate-swift-import-header.sh",
:execution_position => :before_compile }
Library source
I replaced my conditional import with this:
#import "GeneratedSwiftImport.h"
I also ignored the GeneratedSwiftImport.h file in Git.
I am using Xcode 7.3, and I am getting an "Ambiguous expansion of macro" warning, for a macro which was defined in Foundation, but which I have undefined and re-defined in my prefix file. I have modules enabled.
To reproduce:
Set "Enable Modules (C and Objective-C)" to Yes in build settings
Use the following prefix file:
#import <Foundation/Foundation.h>
#undef assert
#define assert(e) NSLog(#"hi") // implementation is not important
Use the following main source file:
int main() {
assert(42);
return 0;
}
Then build in Xcode.
It shows an "Ambiguous expansion of macro 'assert'" warning on the line in the source file that uses the "assert" macro. The "Expanding this definition of 'assert'" points to the definition from the system header, not my redefinition. The "Other definition of 'assert'" points to the definition in my prefix file.
This warning does not happen when modules is disabled.
This is a bug in Xcode; we'd appreciate if you could file a bug report at https://bugreport.apple.com and leave the bug # in a comment here. Your options for working around this bug in the meantime are:
You could use a different name than "assert" for this macro.
You could set the GCC_PRECOMPILE_PREFIX_HEADER build setting to NO, since PCH don’t provide a lot of benefit when you already have modules. The prefix header will still work, it just won’t be turned into a PCH.
You could turn off modules.
I am trying to create a Cocoa Framework from XMPPFramework (which, despite its name is not a Framework, but just a bunch of files).
I am doing this because the XMPPFramework project contains a lot of moving parts (copied source files from other projects, optional source files, weird includes) and we are trying to abstract this away from our main project and include it using Carthage like any other framework.
It almost works. I could include all the files, bundle it into a Framework in Xcode and build it with Carthage. There remains one only problem. Some public .h files contain funny includes like:
#if !(TARGET_IPHONE_SIMULATOR)
#import libxml;
#else
#import libxmlSimu;
#endif
With a custom modulemap:
module libxml [system] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/libxml2/libxml/tree.h"
export *
}
module libxmlSimu [system] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/libxml2/libxml/tree.h"
export *
}
module dnssd [system] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/dns_sd.h"
export *
}
module dnssdSimu [system] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/dns_sd.h"
export *
}
You can find the related commit here.
I added the path of the modulemap file in the Headers search path build settings of Xcode. Compilation of the framework works fine.
However, when I include this header in my main project, those custom modules are not found and compilation fails. This is because those custom modules are not exported and the main project does not see them.
I tried to create a custom modulemap file instead of having Xcode generating a generic one.
framework module XMPPFramework {
umbrella header "XMPPFramework.h"
export *
module * { export * }
}
module libxml [system] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/libxml2/libxml/tree.h"
export *
}
module libxmlSimu [system] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/libxml2/libxml/tree.h"
export *
}
module dnssd [system] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/dns_sd.h"
export *
}
module dnssdSimu [system] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/dns_sd.h"
export *
}
And adding it to the Xcode config:
That's where I get into problems! It now seems that the custom modules are defined twice! Once by the XMPPFramework's modulemap file, and once by me.
Fine! I said. I'm just going to remove the modulemap path from the Header search path and it will solve it. Well, it does not... Now the custom modules cannot be found anymore:
To summarize:
I need to define the custom modules in my modulemap otherwise the main project does not see them and is unable to compile.
If I include the XMPPFramework's modulemap path in Header search path, I get a "duplicate module" error and it does not compile.
If I include my own modulemap path in Header search path, I also get the "duplicate module" error.
If I do not include a modulemap path in Header search path, the compiler does not see the modules and it does not compile.
How can I declare custom modules in my modulemap so that they are exported, and also use them while compiling the project?