引用实例方法需要等效(SWIFT)
Referencing instance method requires equivalency (SWIFT)
我正在尝试利用 SwiftUI 和 Combine 来存储我的应用程序的用户默认设置。查看其他几篇文章中的建议,我已经更新了我的代码,如下所示。但是,我现在收到 "Referencing instance method 'send()' on 'Subject' requires the types 'Setup' and 'Void' be equivalent" 的错误。有人建议我在 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)
}
}
}
send
方法要求你传递主题的输入类型,否则失败完成。所以你的 send
行应该通过 Setup
;
objectWillChange.send(self)
也就是说,在大多数 SwiftUI 代码中,PassthroughSubject
是 <Void, Never>
(这样 send()
不需要参数)。目前尚不清楚您所描述的崩溃的根源是什么;我们需要查看崩溃中涉及的代码才能对其进行调试。到目前为止我还没有复制它。
SwiftUI 不使用 PassthroughSubject
,它使用 ObservableObjectPublisher
。我很确定那是 PassthroughSubject<Void, Never>
的别名,但我不确定。 ObservableObject
协议为您定义了正确的 objectWillChange
,因此您能做的最好的事情就是删除您的定义。
发布者是 objectWillChange
,顾名思义,它应该在 willSet
而不是 didSet
中发送,我认为这并不重要,但 Apple 从 didSet
到 willSet
,我猜他们有充分的理由。
错误是因为您已将 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 和 Combine 来存储我的应用程序的用户默认设置。查看其他几篇文章中的建议,我已经更新了我的代码,如下所示。但是,我现在收到 "Referencing instance method 'send()' on 'Subject' requires the types 'Setup' and 'Void' be equivalent" 的错误。有人建议我在 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)
}
}
}
send
方法要求你传递主题的输入类型,否则失败完成。所以你的 send
行应该通过 Setup
;
objectWillChange.send(self)
也就是说,在大多数 SwiftUI 代码中,PassthroughSubject
是 <Void, Never>
(这样 send()
不需要参数)。目前尚不清楚您所描述的崩溃的根源是什么;我们需要查看崩溃中涉及的代码才能对其进行调试。到目前为止我还没有复制它。
SwiftUI 不使用 PassthroughSubject
,它使用 ObservableObjectPublisher
。我很确定那是 PassthroughSubject<Void, Never>
的别名,但我不确定。 ObservableObject
协议为您定义了正确的 objectWillChange
,因此您能做的最好的事情就是删除您的定义。
发布者是 objectWillChange
,顾名思义,它应该在 willSet
而不是 didSet
中发送,我认为这并不重要,但 Apple 从 didSet
到 willSet
,我猜他们有充分的理由。
错误是因为您已将 Output
类型声明为 Setup
,但您正在使用 Void
.
所以你必须将 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)
}
}
}