我有一个项目,桥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))
}
}
我已经将自动生成的桥接头文件导入到我想使用Plugin
接口的Objective-C.m
文件中:
#import "My_App_Name-Swift.h"
桥接头肯定工作得很好,因为其他桥接的Swift代码都在工作。
我还在Objective-C.h
头文件中转发声明了协议:
@protocol Plugin;
现在,在Objective-C.m
文件中,我有一个NSMutableDictionary,_plugins
的值是那些在Swift中定义的实现Plugin
协议的类的对象。我想遍历每个对象并调用协议中定义的onDevicePackageReceived(np: NetworkPackage)
函数,我计划通过确认对象到实现了该函数的Plugin
协议来实现这一点。
for (Plugin* plugin in [_plugins allValues]) {
[plugin onDevicePackageReceived:np];
}
但是它一直抛出错误Use of undeclared identifier 'Plugin'
。
我检查了自动生成的头文件,它似乎正确地桥接了它:
SWIFT_PROTOCOL("_TtP16KDE_Connect_Test6Plugin_")
@protocol Plugin
- (BOOL)onDevicePackageReceivedWithNp:(NetworkPackage * _Nonnull)np SWIFT_WARN_UNUSED_RESULT;
@end
作为进一步的参考,字典plugins
过去是在Swift中声明的,在Swift中相同的For循环工作得很好:
for plugin in plugins.values {
(plugin as! Plugin).onDevicePackageReceived(np: np)
}
所以本质上,plugins
现在已经被移动到Objective-C,我试图复制这个精确的for循环在Object-C中,唯一的区别是协议Plugin
和所有实现它的类都是在Swift中声明的,所以他们需要被正确导入到Objective-C。
这个语法对于ObjC:
中的协议是不正确的for (Plugin* plugin in [_plugins allValues]) {
没有指向协议存在的指针。ObjC不像Swift那样具有存在类型(即包含符合协议的类型的框)。
我相信你的意思是:
for (id<Plugin> plugin in [_plugins allValues]) {
这是一个符合Plugin.">
的任意ObjC对象(id
)。有关ObjC协议语法的详细信息,请参见Objective-C编程中的使用协议。
关于Swift协议存在性的详细信息,请参见《Swift编程语言》中的协议类型(Protocols as Types)。
如果你不想写objc代码,另一个选择是为你的objc类创建快速扩展。
例如LegacyPluginHolder
,添加新文件LegacyPluginHolder+Extensions.swift
并创建扩展名:
extension LegacyPluginHolder {
@objc func notifyAllPlugins(package: NetworkPackage) {
// Your swift code moves here
}
}
在LegacyPluginHolder.m
中,你可以使用这样的扩展:
[self notifyAllPluginsWithPackage:np]