实际上,您不能真正将协议扩展的功能标记为@objc(或dynamic,顺便说一句等效)。Objective-C 运行时只允许分派一个类的方法。
在您的特定情况下,如果您真的想通过协议扩展来实现,我可以提出以下解决方案(假设您的原始协议名为ObjcProtocol)。
让我们为我们的通知处理程序制作一个包装器:
final class InternalNotificationHandler {
private let source: ObjcProtocol
init(source: ObjcProtocol) {
// We require source object in case we need access some properties etc.
self.source = source
}
@objc func presetLoaded(notification: NSNotification) {
// Your notification logic here
}
}
现在我们需要扩展我们的ObjcProtocol来引入所需的逻辑
import Foundation
import ObjectiveC
internal var NotificationAssociatedObjectHandle: UInt8 = 0
extension ObjcProtocol {
// This stored variable represent a "singleton" concept
// But since protocol extension can only have stored properties we save it via Objective-C runtime
private var notificationHandler: InternalNotificationHandler {
// Try to an get associated instance of our handler
guard let associatedObj = objc_getAssociatedObject(self, &NotificationAssociatedObjectHandle)
as? InternalNotificationHandler else {
// If we do not have any associated create and store it
let newAssociatedObj = InternalNotificationHandler(source: self)
objc_setAssociatedObject(self,
&NotificationAssociatedObjectHandle,
newAssociatedObj,
objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return newAssociatedObj
}
return associatedObj
}
func registerForPresetLoadedNotification() {
NSNotificationCenter.defaultCenter().addObserver(self,
selector: #selector(notificationHandler.presetLoaded(_:)),
name: kPresetLoadedNotificationName,
object: self)
}
func unregisterForPresetLoadedNotification() {
// Clear notification observer and associated objects
NSNotificationCenter.defaultCenter().removeObserver(self,
name: kPresetLoadedNotificationName,
object: self)
objc_removeAssociatedObjects(self)
}
}
我知道这可能看起来不那么优雅,所以我真的会考虑改变一种核心方法。
注意事项:您可能确实想限制您的协议扩展
extension ObjcProtocol where Self: SomeProtocolOrClass