如何在 Objective-C 代码中使用导入的 Swift 协议和 类?

How to use imported Swift protocols and classes in Objective-C code?

我有一个连接 Swift 和 Objective-C 的项目,并且:

我在 Swift 文件中定义了一个 @objc 协议:

@objc protocol Plugin {
    @objc func onDevicePackageReceived(np: NetworkPackage) -> Bool
}

所有实现该协议的类也在Swift中定义,如:

@objc class Ping : NSObject, Plugin {
    
    @objc func onDevicePackageReceived(np: NetworkPackage) -> Bool {
        if (np._Type == PACKAGE_TYPE_PING) {
            connectedDevicesViewModel.showPingAlert()
            return true
        }
        return false
    }
    
    @objc func sendPing(deviceId: String) -> Void {
        let np: NetworkPackage = NetworkPackage(type: PACKAGE_TYPE_PING)
        let device: Device = backgroundService._devices[deviceId] as! Device
        device.send(np, tag: Int(PACKAGE_TAG_PING))
    }
}

我已经将自动生成的桥接 header 文件导入到 Objective-C .m 文件中,我想在以下位置使用 Plugin 接口:

#import "My_App_Name-Swift.h"

桥接 header 肯定工作正常,因为其他桥接 Swift 代码正在工作。

我还在 Objective-C .h header 文件中转发声明了该协议:

@protocol Plugin;

现在,在 Objective-C .m 文件中,我有一个 NSMutableDictionary,_plugins 的值是 类 定义的 objects在 Swift 中实现 Plugin 协议。我想遍历每个 objects 并调用协议中定义的 onDevicePackageReceived(np: NetworkPackage) 函数,我计划通过确认 objects 到 Plugin 协议来实现实现了该功能。

for (Plugin* plugin in [_plugins allValues]) {
    [plugin onDevicePackageReceived:np];
}

但它一直抛出错误 Use of undeclared identifier 'Plugin'

我检查了自动生成的 header 文件,它似乎已正确桥接:

SWIFT_PROTOCOL("_TtP16KDE_Connect_Test6Plugin_")
@protocol Plugin
- (BOOL)onDevicePackageReceivedWithNp:(NetworkPackage * _Nonnull)np        SWIFT_WARN_UNUSED_RESULT;
@end

为了进一步参考,字典 plugins 曾经在 Swift 中声明,其中相同的 for 循环在 Swift 中工作得很好:

for plugin in plugins.values {
    (plugin as! Plugin).onDevicePackageReceived(np: np)
}

所以基本上,plugins 现在已经移动到 Objective-C,我正在尝试在 Object-C 中复制这个精确的 for 循环,唯一的区别是协议Plugin 和实现它的所有 类 都在 Swift 中声明,因此需要将它们正确导入到 Objective-C.

此语法对于 ObjC 中的协议不正确:

for (Plugin* plugin in [_plugins allValues]) {

没有指向协议存在的指针。 ObjC 没有像 Swift 这样的存在类型(即包含符合协议的类型的框)。

我相信你的意思是:

for (id<Plugin> plugin in [_plugins allValues]) {

这是“符合插件的任意 ObjC 对象 (id)。”

有关 ObjC 协议语法的详细信息,请参阅 Objective-C 编程中的 Working with Protocols

请参阅 Swift 编程语言中的 Protocols as Types,了解有关 Swift 协议存在性(与协议本身不同)的详细信息。

如果您不想编写 objc 代码,另一种选择是为您的 objc swift 创建扩展 class。
例如,如果它被称为 LegacyPluginHolder,添加新文件 LegacyPluginHolder+Extensions.swift 并创建扩展名:

extension LegacyPluginHolder {

    @objc func notifyAllPlugins(package: NetworkPackage) {
        // Your swift code moves here
    }
}

LegacyPluginHolder.m 中,您可以像这样使用扩展程序:

[self notifyAllPluginsWithPackage:np]