如何在 objective-c 项目中制作 Swift 包 importable/usable?

How to make a Swift package importable/usable in an objective-c project?

我有一个只用 Swift 编写的程序包,现在我想让它适用于 objective-c 项目。我知道通常在同一个目标中使用 Swift 类 你可以使用为模块创建的桥接 header,但是当我通过 SPM 导入我的包时,没有提示创建一个桥接 header。这可能吗?我是否必须先以某些方式准备我的 swift 包裹?

网上关于这个的文档少得惊人,但我终于弄明白了。这不像在 package.Swift 文件中进行一些更改并单击一些按钮那么容易,但幸运的是它也不是太难。我仍在努力使我的 Swift 库在 Objc 中可用,并将使用我在此过程中发现的任何发现更新此答案,但这是我目前所拥有的:

  1. Swift中的class如果继承自NSObject
  2. ,则只能在objc中使用
public final class MyObjcLibrary: NSObject {}
  1. 要导出到objc,需要追加@objc关键字,并且可以在关键字后面用括号指定objc代码使用的class名称——这个非常方便你的 objc class 只是一个包装器,带有一堆你对应的 Swift class:
  2. 的导出函数
@objc(MyLibrary)
public final class MyObjcLibrary: NSObject{}

这样,您图书馆的用户就可以写 [MyLibrary alloc] 而不是 [MyObjcLibrary alloc]

  1. 现在您可以在新 class 中添加用户需要使用的所有功能(使用 @objc 关键字)。假设您有一个名为 MyLibrary:
  2. 的 Swift class
@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. 要在您的 objc 代码中导入和调用您的 classes 和函数,您只需像添加 Swift 包一样通过 SPM、Cocoapods 等添加包,然后在你的对象 class:
@import MyPackage

...

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

注意函数在 objc 中的命名方式 - 如果第一个参数不是以前缀“with”开头,它会自动添加到 objc 函数签名中,例如doSomethingElseWithID.

我遇到的问题:

  • 当您的 Swift 库有更新时,有时您需要重新启动 Xcode 并删除 DerivedData 文件夹,以便使用更新的代码重新生成桥接头文件。