Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use an Objective-C class in my Swift framework library?

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.

like image 422
kailoon Avatar asked Aug 06 '16 04:08

kailoon


People also ask

Is possible to use an Objective-C framework in Swift?

You can use Objective-C and Swift files together in a single project, no matter which language the project used originally. This makes creating mixed-language app and framework targets as straightforward as creating an app or framework target written in a single language.

Can Objective-C class inherit from Swift class?

Unfortunately, it's not possible to subclass a Swift class in Objective-C. Straight from the docs: You cannot subclass a Swift class in Objective-C.

Is Objective-C and Swift the same?

For starters, Swift is easier to read and write than Objective-C. Swift also has a more concise syntax that makes it easier to understand code at a glance. In addition, Swift is more type-safe than Objective-C, meaning that it is less likely to produce unexpected results due to type mismatches.


1 Answers

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
like image 99
kailoon Avatar answered Sep 28 '22 01:09

kailoon