Can't import CommonCrypto in mixed language framework - ios

I'm building a mixed language framework. I mainly have Swift files, and a few Objective-C ones.
One of the Objective-C files is a crypto class that uses CommonCrypto.
It seems that I can't import it for some reason, even though that I can import it in a Objective-C framework.
Can someone explain to me why that is?
All the other solutions that I found talk about how to use CommonCrypto in Swift when I need to use it in Objective-C in a Swift framework.
P.S:
I tried adding the import in the umbrella header file like so:
#import <CommonCrypto/CommonCrypto.h>
the error: Include of non-modular header inside framework module 'name of header'
This answer did not fix the problem: answer

I've encountered this very problem myself. Here's how you resolve it:
Create a module map file (here's my file).
Copy the latest CommonCrypto.h header.
Create a directory CommonCrypto for both these files.
Copy the directory (via drag-and-drop) to your project.
Add the directory path under SWIFT_INCLUDE_PATHS for your target framework.
This should allow you to use import CommonCrypto wherever you want (for Swift, not Objective-C).
Edit: Seems like I misread the question initially. You want to use CommonCrypto in Objective-C and then use that from Swift. Here's some advice: don't #import CommonCrypto in your public headers, but rather just internally. Wrap all your crypto-structures so that there's no public dependency for CommonCrypto whatsoever, and then just use it from Swift via the default bridging procedure.

Related

SWIFT_OBJC_BRIDGING_HEADER in Swift Package Manager

I am trying to utilize an Objective-C framework inside the Swift package. For this, I would need to import the headers something like
#import<Framework/header.h>
Traditionally this can be achieved via bridging header. How can I set the bridging header via package manager settings?
This is bit tricky. You cannot import Objective-C framework's header files directly into SPM as you cannot write import statement such that #import<Framework/header.h>
The only feasible way is, write swift interface for your header files in Framework and then you would be able to import all methods. It can be done with module map as referred here

Could not build Objective-C module, when using swift in objective-c module

In an iOS application I have a subproject (not cocoapods) in which I have included a swift file and ObjC file (that is used by the swift file). XCode automatically created a bridging file but could not build it because apparantly bridging is not allowed in a framework. The workaround that I used was to add the objective-c header to the umbrella file and it worked. Now I need to use a swift class from ObjC. I have define module to set to YES, the generated file Framework-Swift.h . But when I try to import it in objective-c i get
Could not build Objective-C module
The closest I got after some googleing was this answer:
Ah gotcha. It looks like you're building a mixed Swift & Objective-C
pod - if that's the case, Xcode will try to import
within the generated -Swift.h header.
You'll need to create the header manually and add imports for the
Objective-C classes that you want to expose to Swift.
CocoaPods generates an umbrella header automatically and imports it
within the .modulemap, but Xcode doesn't use that when generating the
-Swift.h header
But I am unsure what header needs to be created manually.
Any ideeas or pointer about using swift in an objective-c framework ? In both ways ?
I also had similar issue when using Swift pods in my Swift project containing several targets. No Objective-C code at all. I tried to clear build folder, pods cache, derived data - nothing worked.
Solution:
Open the Build Settings for a target that contains your module code. Set the "Install Objective-C Compatibility Header" to "No"
There's a great and simple article that wraps up this case:
DEFINES_MODULE=YES
To use ObjC classes in Swift, create a bridging header and specify path to it in the build settings
To use Swift classes in ObjC, #import <ModuleName/ModuleName-Swift.h> in your *.m file (use #class SwiftClass; forward declaration in *.h file, if needed)
For swift classes and their members to be visible to objc
inherit your class from NSObject
prepend it with #objcMembers
make both the class and its members public

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"

How to use an Obj-c Library/Custom interface in a Swift Project

Trying to understand how I can use this in my swift project.
https://github.com/Grouper/FlatUIKit
I have copied the classes folder into my project but am not sure how to use the various .h and .m files. How would I go about using these files within my storyboard to use the custom appearances?
Did some searching and wasn't really able to understand the various threads that I found.
A bit of a broad question so I'll try to provide some basics and hopefully that helps.
If you are unaware, there is a whole book written by Apple about how to use objective-c with swift. it's available on iBooks for free Using Swift with Cocoa and Objective-C (Swift 2.1) by Apple Inc
Here is the online link
You will need to create an objective-c bridging header and import your code through the header.
Your bridging header would look like this:
#import "XYZCustomCell.h"
#import "XYZCustomView.h"
#import "XYZCustomViewController.h"
If they don't have any modules then you can use them in your swift code and it should see them. According to Apple:
Use your custom Objective-C code with the same Swift syntax you use with system classes.
let myCell = XYZCustomCell()
myCell.subtitle = "A custom cell"
If you are importing an Objective-c framework then it should already contain and umbrella header file that takes care of the bridging header stuff for you. then you just import the framework name into the class that you are planning on using.
import MyCustomFramework
Link to the apple docs here
For this, you can use a bridging header, which is used to expose Objective C code to swift. To do this, make a new header file in your project. Import the header files you would like to use in the new header file like this:
#import <FlatUIKit/FlatUIKit.h>
And then, in the build settings of your project, define the Objective-C bridging header to be the header file you just created. Now in any swift files that you would like to use the library in just import the classes like this:
import FlatUIKit
Hope this helps!

What is an alternative to pch in swift?

I was wondering what could be used instead of pch in swift.
Is there any alternative to pch or way to get rid of import in swift so that we don't need to do this for all classes.
I don't want to carry around/import all the time. What could be the best substitute of pch in swift.
You cannot define "Macros" in swift, so there is no ".pch" file for swift.
Also, Swift doesn't have separate "Header (.h) and Implementation (.m)", so there is no need of predefined headers which are needed to compile.
For more information refer to this question, Why .pch file not available in swift?
Class Import Problem:
In Swift, you don't need to write "import" statement for your project classes everywhere. You can access the project classes just by creating their objects.
Pods:
If you are using pods then it's necessary to import frameworks in
every class where you are using.
Third Party Swift Frameworks:
For external Frameworks/Modules, you can create a bridging header file
and replace the below line with your framework/module name:
#import ModuleName;
Reference: Implicitly import specific Swift module
There is no Swift equivalent for Objective-C .pch files.
Module is alternative for it.

Resources