7

I have a package that's written in Swift only, and now I'd love to make it work for objective-c projects. I know usually to use Swift classes in the same target you can use the bridging header created for the module, but when I import my package through SPM, there is no prompt to create a bridging header. Is this possible? Do I have to prep my swift package in certain ways first?

1 Answer 1

10

There is surprisingly little amount of documentation about this online, but I finally figured it out. It's not as easy as making some change in your package.Swift file and click some buttons, but luckily it's not too difficult either. I'm still working on fully making my Swift library to be usable in Objc, and will update this answer with any findings I find along the way, but here is what I have so far:

  1. A class in Swift can only be used in objc if it inherits from NSObject
public final class MyObjcLibrary: NSObject {}
  1. To export it to objc, you need to append the @objc keyword, and you can specify the class name used by objc code with a parentheses following the keyword - this is very handy when your objc class is just a wrapper with a bunch of exported functions of your corresponding Swift class:
@objc(MyLibrary)
public final class MyObjcLibrary: NSObject{}

This way, the user of your library can write [MyLibrary alloc] instead of [MyObjcLibrary alloc].

  1. Now you can add all the functions (with the @objc keyword) your users need to use in your new class. Assuming you have a Swift class named MyLibrary:
@objc(MyLibrary)
public final class MyObjcLibrary: NSObject{
  private var myLibrary: MyLibrary

  @objc public init() {
    myLibrary = MyLibrary()
  }

  @objc public static func doSomething(withID: String) {
    myLibrary.doSomething(withID)
  }

  @objc public static func doSomethingElse(ID: String) {
    myLibrary.doSomethingElse(ID)
  }
  ...
}
  1. To import and call your classes and functions in your objc code, you just add the package the same way you add a Swift package, through SPM, Cocoapods, etc, then in your objc class:
@import MyPackage

...

[[MyLibrary alloc] init];
[MyLibrary doSomethingWithID:@"my_id"];
[MyLibrary doSomethingElseWithID:@"my_id"];
...

Notice how the functions are named in objc - if the first parameter does not start with the prefix "with", it's automatically added for the objc function signature, e.g. doSomethingElseWithID.

Problems I've seen:

  • when your Swift library has updates, sometimes you need to restart Xcode and remove your DerivedData folder for the bridging header files to be regenerated with updated code.
Sign up to request clarification or add additional context in comments.

5 Comments

You're not saying anything that isn't pretty well known, and what you're saying has nothing whatever to do with SPM per se; but it's great that you've discovered it for yourself. I would just also call your attention to @objcMembers which can save a lot of typing.
It might be very well known among people who have the right experience, but for someone who's new to iOS development and starting from Swift, figuring out how to make my library usable in objc has been a struggle. Let me know if you have some good resource that explains all of these. I couldn't find one and basically figured this out myself by reading other people's code and trial and error myself. I agree this is not related to SPM at this point. Initially when I asked the question (2 weeks ago) I thought it was, I should edit my question.
Thanks for the mention of @objcMembers btw, looking into it now! I have done a lot of googling on this topic and I have not seen it.
My book summarizes quite fully how Objective-C is exposed to Swift and how Swift is exposed to Objective-C. The free online excerpts are free and online, but somewhat outdated (the discussion is vastly improved in more recent versions): apeth.com/swiftBook/apa.html#_objective_c
That's great, will give it a read! The reason I posted my learnings here is that it's not very easy for someone to find the answer to "how to make swift library usable in objc" online quickly, so I hope this helps someone.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.