using module.modulemap to integrate frameworks' objC header in Swift class - ios

I have a framework that contains Objective-C header files. I want to use these header files in the Swift project, in which I am importing this framework.
There are two ways to do it
1) create bridging header file - but, then user will be dependent to create this file, while integrating the framework
2) create module.modulemap file - that I can ship with my framework and user can add it to (which build setting).... <- I need help here
I've tried Import Paths in Swift Compiler - Search Paths and Module Map File in Packaging
In both the cases, I am not able to import the header RandomHeader.
My module.modulemap looks like below
module ToBeShippedFramework
{
header "RandomPublicHeader.h"
export *
}
Is there something different that I need to do?
PS: Please put in comments if you need some more info to understand this question more clearly.

Related

How do I build an iOS Framework with the FIT C++ library

I am trying to create a Swift wrapper for the FIT C++ libFitSdkCppiOS.a library but don't really know how to set things up with the mix of C++, Objective-C and Swift code.
Here is what I have done so far:
1. Created a new target for the FITFramework
2. Copied the libFitSdkCppiOS.a library and the associated cpp header files into the targets folder in Xcode
3. Because you can't use a Bridging-Header file in Frameworks I am trying to figure out how what to do next.
I have seen a few posts about something called an umbrella header but have no idea what that is or what needs to be in it to get this to work. Can someone please explain step by step what I need to do to create this Swift Wrapper and package it up as a framework that can be used by other projects.
Is the umbrella header the main framework header file, in this case the one called FITFramework.h ?
If not how do I create an umbrella header file and where does it need to be?
What should be in the umbrella header file?
FITFramework.h
//
// FITFramework.h
// FITFramework
//
// Created by xxxx xxxxxxx on 7/6/18.
//
#import <UIKit/UIKit.h>
//! Project version number for FITFramework.
FOUNDATION_EXPORT double FITFrameworkVersionNumber;
//! Project version string for FITFramework.
FOUNDATION_EXPORT const unsigned char FITFrameworkVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <FITFramework/PublicHeader.h>
EDIT:
1. How do I expose the Objective-C classes to Swift without using a Bridging-Header file ?
There are a few articles that mention the use of a module.map file but this seems to be to expose the C headers rather than the Objective-C headers to the Swift wrapper function
OK I figured it out - and it was hard to find any good or accurate guides. I will write it up in more detail elsewhere and add a link at some point.
In the meantime - assuming your framework is call XXXFramework - you need to:
create a XXXFrameworkPrivate subdirectory in the XXXFramework folder with a module.modulemap file in it
add the private headers to the module.modulemap file like so
module FitFrameworkPrivate {
header "../XXX.h"
header "../YYY.h"
header "../ZZZ.h"
export *
}
create a XXX.xcconfig file with the following line
SWIFT_INCLUDE_PATHS = $(SRCROOT)/XXXFramework/XXXFrameworkPrivate
set the project configuration to use this config file for both debug and release
add this line to your Swift classes
import XXXFrameworkPrivate
Basically this allows Swift classes to import the headers from the module.modulemap file instead of using a Bridging-Header file which can't be used in a Framework.
Watch out though - I have callbacks between the C++ classes, the Objective-C classes and the Swift classes and this creates a problem if your public class uses a protocol to communicate with one of the private Obj-C classes. To avoid that add another public Swift class that talks to the Swift wrapper and only have that one public.
If anyone has a better way of doing it please let me know.
Thanks a lot! This answer was very useful to me as I had similar issue (to integrate the c fit sdk instead of the c++ fit sdk into a swift framework for macOS and iOS apps)
I'll just add the follow step I had to do, in case it helps someone:
When using the framework in a app that used Pods, I wasn't able to include the "Private" framework (necessary because it contains the c constant converted to swift constant like FIT_MESG_XXX) and the xcconfig are set by the Pods framework. Editing the Pods xcconfig worked, but clearly bad.
Eventually, I figured out you can just create a new xconfig with a #include and use that in the external app where you want to use like so (this is separate from the xcconfig you need to build the framework)
#include "../Pods/Target Support Files/Pods-iOSorMac/Pods-iOSorMacOSApp.debug.xcconfig"
SWIFT_INCLUDE_PATHS="$(SRCROOT)/fit-sdk-swift/RZFitFile/sdk" "$(SRCROOT)/fit-sdk-swift/RZFitFile/src"

Unable to import bridging header

Im trying to link an external Objective-C framework, "frameworkSDK", to my swift project. However I seem to be getting this error :
<unknown>:0: error: failed to import bridging header
I've looked at loads of solutions to my problem but non of them seem to work. Here's what I've done so far :
I've created a "bridingfile.h" at the root of the project and
imported "frameworkSDK.frameworkSDK.h" to the file.
I've made sure Objective-C Bridging Header path was correct under
Swift Compiler - Code Generation.
I've changed my framework search paths to the where the
"frameworkSDK" is located - Code Generation.
Added the path to "bridgingfile.h" to Header Search Paths - Code
Generation.
I've tried to instead create the bridgingfile 1 directory in from
the root folder, and then update accordingly.
Any help would be greatly appreciated! :)
If you are importing an external Objective-C framework, i.e. one stored in, say, frameworkSDK.framework directory structure (bundle), you should not have to worry about a bridging header. Instead do the following:
Under Build Settings set Framework Search Paths to the parent
directory of the frameworkSDK.framework directory.
Also under Build Settings set Runpath Search Paths to
$(FRAMEWORK_SEARCH_PATHS) #executable_path/../Frameworks.
In a Swift file where you want to use the Objective-C framework do
import frameworkSDK.

How to import Objc Files into my Swift files within my custom cocoapods framework?

Simple explanation. I have created my own pod with name BSSelectableView, but within I need to use two files written in Objective-C. What do I need to achieve?
I need to make it visible within my Swift files, and also for people who will install my pod.
Your Target needs a Bridging Header.
This is an Objective-C-Header-File with the name [TargetName]-Bridging-Header.h
Within this file, you have to #import all Objective-C-Headers you want to use in your Swift-Files.
You don't have to import anything in your Swift files.
More information about Swift and Objective-C mixed projects
You need to create a [TargetName]-Bridging-Header file in your project.
import all the header files in bridging header file
Now you can use all objective c file in swift.

Xcode can't find header file

I am trying to make a framework for my project. Into my framework I added the path of my header files to target>Build Settings>header-search path. After that I added this framework to my project by Build Phases>Link Binary With Libraries.
When I want to import the header file which I included in my framework, I get a .h file not found error. Is what I'm trying to do possible? Or am I missing anything?
I created framework like that;
Opened new project as iOS>Framework&Library>Cocoa Touch Framework
I didn't add any class, i just added header search path and library search path and linker flags. I don't think i did a mistake in this part because we do it in every project but first time i m doing this for framework. Then i pressed run and get my framework from Products.
I opened my project and added framework Build Phases>Link Binary With Libraries. I m able to import header file of framework like #import <myframework/framework.h>
After this i added framework also General>Embedded Binaries. Everything look normal but i cannot add headers to my project which i included to my framework with header search path. I have to use header search path because there is tons of headers, i cannot add all of them to my Xcode.
Make sure you all Public Header appears in Public Section else drag and drop .h file to public
Everything look normal but i cannot add headers to my project which i included to my framework with header search path.
It sounds as though you're expecting all the headers that can be found at the path specified by your header search path will become part of your framework, so that if there's a header named SomeHeader.h in your search path, it will be built into your framework and you'll be able to import it into client projects like:
#import <MyFramework/SomeHeader.h>
But that's not the case at all. If you want your framework to provide SomeHeader.h, you need to add that file to the project and, as Meghs Dhameliya already pointed out, you need to specify SomeHeader.h in the Public Headers portion of the Headers build phase. This will make Xcode copy the header file into the framework so that clients of the framework can import the header file. It's not clear that that's what you really want, though... in comments you wrote:
There is a lot of headers in another path. I have to use header search path unfortunately. Kind of company rule.
So it sounds like all projects in your company specify the same header search path so that they have access to these header files. If that's true, then there's no reason for projects to need to #import them from your framework, but in that case it's not clear what the actual problem is. Or, perhaps you're creating the framework so that client projects can get the headers from your framework instead of having to reference the header search path. In that case, you will need to add those headers to the project and specify them as described above.

How to use third party lib in embedded dynamic framework for iOS with swift

Now I have a project, like testApp, using some third party lib like alamofire and some others libs in objective-c.
Now I want to add a today widget. According to some tutorial, I created a new target "testAppKit" as a shared dynamic framework, and target "testAppWidget" as today extension. The common code will be in testAppKit for reuse.
Now I need to use third party libs in testAppKit. And added lib and header in build phases of testAppKit. Then I add #import <theLib/TheHeader.h> in testAppKit.h. But there is an error:
Include of non-modular header inside framework module 'testAppKit'
So, I want to know how to use third party libs (maybe in Swift or Objective-C) in this kind of embedded dynamic framework.
I use Dropbox Datastore API in my app and I finally made it working for embedded Cocoa Touch framework to share code for Containing App and Today Extension.
I figured out that in my Swift file in the embedded framework I can import any 3rd party framework I had in the Project (i.e. Farbic.framework, Crashlytics etc.) but not Dropbox.
What was the difference? The "Modules" folder! Dropbox.framework doesn't provide module map file. So I created it based on what I found in Fabric.framework:
Go to the Dropbox.framework folder in your project direcotry.
Create new folder "Modules" and go inside
Create a file called: "module.modulemap"
The content of the file:
framework module Dropbox {
umbrella header "Dropbox.h"
export *
module * { export * }
}
After doing that I needed to add import path.
Go to your Project file
Select your embedded framework target
Go to the "Build Settings" and find "Swift Compiler - Search Paths"
Add path to your Dropbox.framerowk and set "recursive" option.
I wanted to put a screenshot here but I can't do that yet - because of my "reputation" ;)
Now I'm able to do "import Dropbox" in my swift files :)
Hope this can help you :)

Resources