3

When you add a Swift file to an Objective-C project, Xcode will generate a Swift-to-ObjC header, as described here: http://ericasadun.com/2014/08/21/swift-calling-swift-functions-from-objective-c/

Without this header it is not possible to call Swift code from Objc-C. However Xcode is not auto-generating this header for my framework target.

If I create an Objective-C app and drop a Swift file into it, then it does auto-generate one, so I suspect it's because I'm building a framework and not an app. Without one its not possible to use the Swift code from the Obj-C code.

I tried using the one which was generated for the app (after renaming it and putting it in the appropriate DerivedData folder ) but Xcode didn't update it and actually it will eventually delete it, so manually creating or trying to maintain this file is not feasible.

How can I make Xcode generate this header for a framework target, so that I can call my Swift code from my Obj-C code?

And remember folks: the question is about calling Swift from Obj-C not calling Obj-C from Swift.

Gruntcakes
  • 37,738
  • 44
  • 184
  • 378
  • What do you need? A bridging header or a generated Obj-C interface? – jtbandes Apr 14 '16 at 03:08
  • I need to be able to add Swift source files to an Obj-C framework and to able to invoke the Swift classes from the Obj-C code. – Gruntcakes Apr 14 '16 at 03:13
  • And what problem are you having? – jtbandes Apr 14 '16 at 03:13
  • There is no Swift bridging header generated. Without a Swift bridging header it is not possible to call Swift code from Obj-C code within the same code base. – Gruntcakes Apr 14 '16 at 03:15
  • 1
    Interesting, I just set up a test project and there seems to be a catch-22. Xcode wont generate the "FrameworkName-Swift.h" file unless I specify a bridging header in the Swift compiler build settings, but if I do that then I get an error that "using bridging headers with framework targets is unsupported" – Paulw11 Apr 14 '16 at 03:35
  • Check this out, it may help you: http://stackoverflow.com/questions/32008123/import-sqlite3-h-error-include-of-non-modular-header-inside-framework-module/32010482#32010482 – Abdullah Apr 14 '16 at 03:37
  • This is the correct duplicate link: [Can't use Swift classes inside Objective-C](http://stackoverflow.com/a/27251979/2792531) – nhgrif Apr 14 '16 at 04:09

2 Answers2

10

I created a new Framework project, added both Obj-C and Swift files, and was able to do this:

// MyObjCClass.m

#import "MyObjCClass.h"
#import <MyFramework/MyFramework-Swift.h>

@implementation MyObjCClass
- (void)test {
    [[MySwiftClass alloc] init];
}
@end

Note that your Swift class must be public:

public class MySwiftClass: NSObject {
    // ...
}

More information is available in Apple's Swift/Obj-C interop documentation under "Importing Swift into Objective-C".

jtbandes
  • 115,675
  • 35
  • 233
  • 266
  • 1
    It seems that the `public` modifier is the key. – Paulw11 Apr 14 '16 at 03:47
  • Note that in the documentation I linked, it says: *"[This header] also contains those marked with the `internal` modifier **if your app target has an Objective-C bridging header**."* – jtbandes Apr 14 '16 at 03:50
  • Yeah, I tried `internal` and it didn't work, because you can't have an Objective-C bridging header on a framework – Paulw11 Apr 14 '16 at 03:51
  • Before posting the question I also created a new framework and found I could not do likewise with MyFramework-Swift.h as you have done, and my class *was* public. But the difference is I prefaced the class with @objc and interestingly you haven't. I'll do some more experiments without it and see what happens. – Gruntcakes Apr 14 '16 at 03:52
  • The presence of `@objc` doesn't affect it in my sample project. As far as I can tell, it's necessary to use when importing the header. – jtbandes Apr 14 '16 at 03:54
  • Same here - As long as I have `public` mine now works with & without `@objc` – Paulw11 Apr 14 '16 at 03:55
  • I'm not even clear on what `@objc` even does in Swift exactly... it seems like nonsense. What is certain is that your class has to inherit from `NSObject` (or obviously something else which eventually can follow up the chain to `NSObject`. – nhgrif Apr 14 '16 at 04:01
  • `@objc` is required in some cases, such as when you require a method to be exposed to the Obj-C runtime by a selector, and/or when you want its Obj-C name to be different from its Swift name. – jtbandes Apr 14 '16 at 04:03
  • @jtbandes It's *not* though. You can use the `dynamic` keyword for runtime selectors for timers/NSNotifications, etc... (although I forgot about generating different Swift/Objective-C names). – nhgrif Apr 14 '16 at 04:04
  • `dynamic` is for properties only, I think. – jtbandes Apr 14 '16 at 04:07
  • It's not. I've got a code base with plenty of timers and notifcations and not a single `@objc` in the whole thing. – nhgrif Apr 14 '16 at 04:08
  • OK, I didn't realize `dynamic func` worked. In that case, I have no idea :) – jtbandes Apr 14 '16 at 04:09
  • @nhgrif I [figured out the difference!](http://chat.stackoverflow.com/rooms/109100/discussion-between-jtbandes-and-nhgrif) – jtbandes Apr 14 '16 at 04:27
-2

#import <MyFramework/MyFramework-Swift.h>

ATTENTION: this header file is generated auto!!!! Don't create it manually!!

Shawn
  • 1