It’s a lot easier than the docs make it out to be, especially if you’re just using a single target. Here’s my Swift file. Make sure you use the @objc keyword to tag your Swift classes so they’re available to your ObjC ones.
import Foundation @objc class TestClass { class func `new`() -> TestClass { return TestClass() } func testFunction() { println("This function works") } }
And here’s the Objective-C client:
#import "AppDelegate.h" #import "TestProject-Swift.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { TestClass *instance = [TestClass new]; [instance testFunction]; return YES; } @end
The secret here is to import the name of the target in this case “TestProject” with the “-Swift.h” extension. Xcode builds this for you and hides it behind the scenes in the derived data. For the above example, mine was left at: DerivedData/TestProject-aqpeqeuqusyzdtcqddjdixoppyqn/Build/Intermediates/TestProject.build/Debug-iphoneos/TestProject.build/DerivedSources/TestProject-Swift.h
The .h file is actually quite interesting. Here is the interface that was built from my Swift code:
SWIFT_CLASS("_TtC11TestProject9TestClass") @interface TestClass + (TestClass *)new; - (void)testFunction; - (instancetype)init OBJC_DESIGNATED_INITIALIZER; @end
There’s also a bit of fascinating cookiecutter set-up to be found in the header file. I encourage you to take a peek.
4 Comments
[…] Calling Swift from C. […]
Thanks! One thing that confused me for awhile is that “TestProject-Swift.h” (and its declarations) are unrecognized until after the first build.
Thanks – one thing I noticed it is the $PRODUCT_NAME of your Target – not just the name of your Target ( this confused me for a bit )
the class doesn’t show up with NSClassFromString(), however –
any idea about that?