符合 ObjC 协议的 Swift 属性没有成员“publisher”

问题描述 投票:0回答:1

在更大的 ObjC/Swift 混合代码库中,我有一个 ObjC 协议

MyObjCProtocol <NSObject>
,其他 ObjC 类需要遵守。它声明了一个字符串属性
@property (copy) NSString *myString

现在,我的一个 Swift 对象有一个属性

conformsToObjCProtocol
声明符合此协议:

let conformsToObjCProtocol: MyObjCProtocol

这一切都运作良好。 但是当我尝试像这样使用组合来观察

myString
时:

let cancellable = conformsToObjCProtocol.publisher(for: \.myString).sink { print($0) }

我收到错误

Value of type 'any MyObjCProtocol' has no member 'publisher'

我相信它应该可以工作,因为 MyObjCProtocol 被声明为符合 NSObject。我也将 MyObjCProtocol.h 添加到桥接标头中,所以不是这样。我无法在 Swift 中重写协议,因为我需要 ObjC 类来遵守它。对此我能做什么?

swift objective-c protocols combine
1个回答
0
投票

您面临的问题是由于即使您的协议

MyObjCProtocol
继承自
NSObject
,Combine 也不会自动识别发布属性。
publisher(for:)
方法是Combine为支持键值观察(KVO)的对象提供的扩展,它并不直接应用于Objective-C中的协议。

这里有一个 Swift 解决方案来解决这个问题:

  1. 为 NSObject 创建扩展:您可以为

    NSObject
    创建扩展,为 KVO 兼容属性提供发布者方法。

  2. 使用AnyObject代替MyObjCProtocol:由于Combine需要具体的引用,而你的协议只是一个抽象,所以你需要使用

    AnyObject
    并确保你的具体对象符合协议。

以下是如何执行此操作的示例:

  1. NSObject 扩展:
import Combine
import Foundation

extension NSObject {
    func publisher<T>(for keyPath: KeyPath<NSObject, T>) -> AnyPublisher<T, Never> {
        Publishers.KVObservablePublisher(object: self, keyPath: keyPath)
            .eraseToAnyPublisher()
    }
}
  1. 观察属性
import Combine

// Ensure your concrete object is an NSObject and conforms to the protocol
let objcObject: AnyObject = conformsToObjCProtocol as AnyObject

// Force cast objcObject to NSObject to use the extension
guard let nsObject = objcObject as? NSObject else {
    fatalError("The object is not an NSObject")
}

// Create the publisher and subscribe to it
let cancellable = nsObject.publisher(for: \.myString).sink { newValue in
    print(newValue)
}

确保

myString
在您的 Objective-C 类中正确暴露给 KVO。这应该可以解决问题并允许您使用组合观察属性的变化。

© www.soinside.com 2019 - 2024. All rights reserved.