引用实例方法需要等效性 (SWIFT)
Posted
技术标签:
【中文标题】引用实例方法需要等效性 (SWIFT)【英文标题】:Referencing instance method requires equivalency (SWIFT) 【发布时间】:2019-09-29 20:51:37 【问题描述】:我正在尝试利用 SwiftUI 和 Combine 来存储我的应用程序的用户默认值。查看其他一些帖子中的建议,我已经更新了我的代码,如下所示。但是,我现在收到“在 'Subject' 上引用实例方法 'send()' 需要类型 'Setup' 和 'Void' 等效”的错误。有人建议我在 PassthroughSubject 中将“Setup”更改为 void,但是这会在启动时在应用程序中造成严重崩溃 - “致命错误:找不到 Setup.Type 类型的可观察对象。”
我有点茫然...欢迎任何指点。
============== DataStoreClass ============
import SwiftUI
import Foundation
import Combine
class Setup: ObservableObject
private var notificationSubscription: AnyCancellable?
let objectWillChange = PassthroughSubject<Setup,Never>()
@UserDefault(key: "keyValueBool", defaultValue: false)
var somevalueBool: Bool
didSet
objectWillChange.send() // <====== Referencing instance method 'send()' on 'Subject' requires the types 'Setup' and 'Void' be equivalent
init()
notificationSubscription = NotificationCenter.default.publisher(for: UserDefaults.didChangeNotification).sink _ in
self.objectWillChange.send()
============= property wrapper ===========
import Foundation
@propertyWrapper
struct UserDefault<T>
let key: String
let defaultValue: T
var wrappedValue: T
get
UserDefaults(suiteName: "group.com.my.app")!.value(forKey: key) as? T ?? defaultValue
set
UserDefaults(suiteName: "group.com.my.app")!.set(newValue, forKey: key)
【问题讨论】:
我不是最好的组合编码器,但根据您对<Setup,Never>
的定义,您告诉编译器在您的 send
中您将传递一个 Setup
实例,如 - I想想 - ``objectWillChange.send([在此处插入您的设置实例])`。我只是没有在你的代码中看到这个“设置实例”到底是什么。
【参考方案1】:
错误来自您已将Output
类型声明为Setup
,但您使用Void
调用objectWillChange。
所以你必须将 self 传递给 objectWillChange:
self.objectWillChange.send(self)
需要注意的重要一点是,您应该打电话给objectWillChange
,而不是didSet
,而是willSet
:
var somevalueBool: Bool
willSet
objectWillChange.send(self
你从不设置 somevalueBool,所以这段代码无论如何都不会被调用。
您的设置应大致如下所示:
class Setup: ObservableObject
private var notificationSubscription: AnyCancellable?
public let objectWillChange = PassthroughSubject<Setup,Never>()
@UserDefault(key: "keyValueBool", defaultValue: false)
var somevalueBool: Bool
init()
notificationSubscription = NotificationCenter.default.publisher(for: UserDefaults.didChangeNotification).sink _ in
self.objectWillChange.send(self)
【讨论】:
谢谢,这似乎已经解决了可能的主要问题.. 它仍然不像我想的那样工作,因为我更改值的 SwiftUI 代码似乎没有“触发” willSet()代码。【参考方案2】:send
方法要求您传递主题的输入类型,或者失败完成。所以你的send
行应该通过Setup
;
objectWillChange.send(self)
也就是说,在大多数 SwiftUI 代码中,PassthroughSubject
是 <Void, Never>
(因此 send()
不需要参数)。目前尚不清楚您所描述的崩溃原因是什么;我们需要查看崩溃中涉及的代码来调试它。到目前为止我还没有复制它。
【讨论】:
【参考方案3】:SwiftUI 不使用PassthroughSubject
,它使用ObservableObjectPublisher
。我很确定这是PassthroughSubject<Void, Never>
的别名,但我不确定。 ObservableObject
协议为您定义了正确的objectWillChange
,因此您能做的最好的事情就是删除您的定义。
发布者是objectWillChange
,顾名思义,它应该以willSet
而不是didSet
发送,我认为这并不重要,但Apple 已从didSet
更改为willSet
,而我的猜测是他们有充分的理由。
【讨论】:
以上是关于引用实例方法需要等效性 (SWIFT)的主要内容,如果未能解决你的问题,请参考以下文章
尝试更改对象属性并保持反应性。属性或方法“vm”未在实例上定义,但在渲染期间被引用
JAVA笔记---面向过程与面向对象;类,对象;实例变量,引用;构造方法;