为什么我们可以将存在类型用作用@ObseverObject包裹的属性类型

发布于 2025-02-06 17:54:55 字数 902 浏览 1 评论 0原文

protocol ExampleStore: ObservableObject {
    var text: String { get }
}

class ConcreteExampleStore: ExampleStore {
    @Published var text: String = ""
}

struct ExampleView: View {
    @ObservedObject private var store: any ExampleStore

    init(store: any ExampleStore) {
        self.store = store
    }

    var body: some View {
        Text(store.text)
    }
}

我正在探索Swift 5.7的新功能,并试图制作一个商店协议,我将用作视图中的一种类型。我知道在以前版本的Swift中,这是不可能的,因为ObservableObject协议符合Assectype的exigplestore,因此解决方法是在视图中定义一个符合exkplestore协议的通用参数,但是由于5.7这些协议应该是可用作存在类型吗?

我会收到以下错误:键入'任何extplestore'不能符合'observableObject'。 奇怪的是,该消息出现在商店被声明为视图属性的行上,有人可以理解此错误消息吗?预先感谢:)

“代码和错误消息的屏幕截图”

protocol ExampleStore: ObservableObject {
    var text: String { get }
}

class ConcreteExampleStore: ExampleStore {
    @Published var text: String = ""
}

struct ExampleView: View {
    @ObservedObject private var store: any ExampleStore

    init(store: any ExampleStore) {
        self.store = store
    }

    var body: some View {
        Text(store.text)
    }
}

Im exploring the new features of Swift 5.7 and was trying to make a Store protocol which I would use as a type inside my View. I know that this would not be possible in previous versions of Swift since the ObservableObject protocol which ExampleStore conforms to has an associatedType and therefore the workaround was to define a generic parameter in the View which conforms to ExampleStore protocol, but since 5.7 those protocols should be usable as existential types?

I'm getting the following error: Type 'any ExampleStore' cannot conform to 'ObservableObject'.
It is strange that the message appears on the line where the store is declared as a property of the View, can anyone make sense of this error message? Thanks in advance :)

Screenshot of the code and error message

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

行雁书 2025-02-13 17:54:55

该解决方法虽然无法概括,但需要为每个someProtocol定义。

protocol SomeProtocol: ObservableObject {
    ...
}

ObservableAnySomeProtocol是符合observableObject的具体类,并用作包装器,以传递源对象的更改事件。

@propertyWrapper
@dynamicMemberLookup
class ObservableAnySomeProtocol: ObservableObject {

    var wrappedValue: any SomeProtocol
    var cancellable: AnyCancellable?

    init(wrappedValue: any SomeProtocol) {
        self.wrappedValue = wrappedValue
        self.cancellable = wrappedValue.objectWillChange.sink(receiveValue: { [unowned self] in
            self.objectWillChange.send()
        })
    }

    subscript<T>(dynamicMember keyPath: WritableKeyPath<any SomeProtocol, T>) -> T {
        get {
            wrappedValue[keyPath: keyPath]
        }
        set {
            wrappedValue[keyPath: keyPath] = newValue
        }
    }
}

然后在客户端视图中:

struct MyView: View {
    
    @ObservedObject @ObservableAnySomeProtocol var someObject: any SomeProtocol

    var body: some View {
        ...
    }
}

This workaround works although could not generalize, so needs to be defined for each SomeProtocol.

protocol SomeProtocol: ObservableObject {
    ...
}

ObservableAnySomeProtocol is concrete class that conforms to ObservableObject and serves as a wrapper to pass the change events of source object.

@propertyWrapper
@dynamicMemberLookup
class ObservableAnySomeProtocol: ObservableObject {

    var wrappedValue: any SomeProtocol
    var cancellable: AnyCancellable?

    init(wrappedValue: any SomeProtocol) {
        self.wrappedValue = wrappedValue
        self.cancellable = wrappedValue.objectWillChange.sink(receiveValue: { [unowned self] in
            self.objectWillChange.send()
        })
    }

    subscript<T>(dynamicMember keyPath: WritableKeyPath<any SomeProtocol, T>) -> T {
        get {
            wrappedValue[keyPath: keyPath]
        }
        set {
            wrappedValue[keyPath: keyPath] = newValue
        }
    }
}

Then in a client view:

struct MyView: View {
    
    @ObservedObject @ObservableAnySomeProtocol var someObject: any SomeProtocol

    var body: some View {
        ...
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文