16

I have created a Swift Framework that I use in multiple projects. There is an Objectivce-C class that I would like to use in that is difficult to port in straight Swift. Lets say that class is SFTest

@interface SFTest {
} 
+ (NString *)myMethod(NSString *data);
@end
@implementation SFTest
+ (NString *)myMethod(NSString *data) {
    // does some processing
    return processedData;
}
@end

Can I somehow use this in my Swift framework project, and if yes, how? My research on this mentions something called bridging headers but that they can't be used in Swift frameworks.

kailoon
  • 1,925
  • 1
  • 17
  • 32
  • I dont want to import CommonCrypto to use in Swift. I just want to use an Objective-C class in a Swift Framework. I can remove the common crypto in the code and use a simpler example. – kailoon Aug 06 '16 at 04:14
  • Removed any mention of CommonCrypto so this should be much simpler to answer with a yes or no. – kailoon Aug 06 '16 at 04:18
  • Please take a look at https://stackoverflow.com/a/57682107/4770877 – yoAlex5 Aug 27 '19 at 21:22

2 Answers2

48

So this took a while but I finally got something to run on my device. Here is my setup. I created a Swift Framework called swiftlib. I added an Objective-C class called "MyClass". Basically it looks like this:

enter image description here

I then modified the "umbrella header" to import my new Objective-C class. The umbrella header is the name of your swift library project. So in my case, it was "swiftlib.h". This is what is inside my umbrella header file:

//
//  swiftlib.h
//  swiftlib
//

#import <UIKit/UIKit.h>
#import "MyClass.h"

//! Project version number for swiftlib.
FOUNDATION_EXPORT double swiftlibVersionNumber;

//! Project version string for swiftlib.
FOUNDATION_EXPORT const unsigned char swiftlibVersionString[];

// In this header, you should import all the public headers of your     framework using statements like #import <swiftlib/PublicHeader.h>

Make sure to set your header class to public or you will get a compile error. Basically whatever is included in the umbrella header is exposed to users of your swift framework so it needs to be public. Select MyClass.h and open the right details bar and select the dropdown here:

enter image description here

I then used this Swift framework in a single view application for testing and was able to use my Objective-C class in the AppDelegate.swift like so:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.
        let test = MyClass.myMethod()
        print("test = " + String(test))
        return true
    }

This compiled and ran on my device.

For those curious, this was the implementation code for the Objective-C MyClass:

#import "MyClass.h"
#import <CommonCrypto/CommonCrypto.h>

@implementation MyClass

+ (NSString *)myMethod {
    NSString *key = @"test";
    NSString *data = @"mytestdata";
    const char *ckey = [key cStringUsingEncoding:NSASCIIStringEncoding];
    const char *cdata = [data cStringUsingEncoding:NSASCIIStringEncoding];
    unsigned char chmac[CC_SHA256_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgSHA256, ckey, strlen(ckey), cdata, strlen(cdata), chmac);
    NSData *hmac = [[NSData alloc] initWithBytes:chmac length:sizeof(chmac)];
    NSString *hash = [hmac base64Encoding];
    return hash;
}

@end
kailoon
  • 1,925
  • 1
  • 17
  • 32
  • 6
    You have saved my day ^_^ – Nata Mio Jan 24 '17 at 10:50
  • i've been pulling my hair out for hours. thank you for this detailed solution! – oriyentel Feb 08 '18 at 04:22
  • I havent tried but i hope this works with an ios app. What i am doing is i am using the framework inside another framework... it is giving clang error. Any help would be much appreciated.The first framework which contains objective c classes builds fine. but when i import it in another framework it builds with a clang error. – Pranav Gupta Oct 01 '18 at 06:34
  • 3
    Not Succeed yet. I have also try above solution but got error "Include of non-modular header inside framework module in FrAmeworkNAme " Please help me out – Sazid Iqabal Mar 04 '19 at 11:25
  • @kailoon What if I don't want to expose this objective c file to the end user? Is it doable? – nr5 Jun 20 '19 at 10:52
  • How about if I want to hide these header files from the end user? I just want my framework to internally use these objective-c files. – nr5 Jun 25 '19 at 11:06
  • @SazidIqabal I forgot to make the header public thats why I was getting this error. – DareDevil Feb 05 '20 at 11:11
  • @DareDevil I am getting the same error Include of non-modular header inside framework module in, My header file is marked public even then I see this error. How did you fix this ? – Max Apr 21 '21 at 08:53
  • I just got rid of the objc classes to solve this for now, Keeping it simple. – Max May 11 '21 at 20:10
-10

First use objective c class in your swift project you have to create bridging header file in that file you have to import objective c class and then you can use that class in swift

Chirag Patel
  • 1,293
  • 1
  • 8
  • 20