如何在 Combine in Swift 中的订阅者中引用自己
How to reference self in a Subscriber in Combine in Swift
刚刚开始掌握 Combine 并遇到一个问题,我需要在我的 class 中调用一个方法,当它从 Publisher
接收到一个值时,在本例中是 Notification
来自 NotificationCenter
...
这是订阅...
let subscribe = NotificationCenter.default.publisher(for: Notification.Name(rawValue: "LocalTalkNotificationReceivedData"), object: nil)
.map( {
([=11=].object as! Data)
} )
.sink(receiveValue: {
self.interpretIncoming(data: [=11=])
})
编译器告诉我的是 Use of unresolved identifier 'self'
。
太晚了,我有点累了,有人知道吗?
Xcode Catalina beta 5 上的 11 beta 5 顺便说一句...
完整文件:
import Foundation
import Combine
import SwiftUI
public class MessageData: ObservableObject, Identifiable {
public var peerData: [Peer] = [Peer]()
public var messageData: [Message] = [Message]()
public var objectWillChange = PassthroughSubject<Void, Never>()
let subscribe = NotificationCenter.default.publisher(for: Notification.Name(rawValue: "LocalTalkNotificationReceivedData"), object: nil)
.map( {
([=12=].object as! Data)
} )
.sink(receiveValue: {
self.interpretIncoming(data: [=12=])
})
init() {
self.setupDummyData()
}
private func setupDummyData() {
self.peerData = self.load("peerData.json")
self.messageData = self.load("messageData.json")
}
func addMessage(message: String, sender: MessageSource, name: String) {
let newMessage = Message(id: Date().hashValue,
content: message,
source: sender,
correspondent: name)
self.messageData.append(newMessage)
self.objectWillChange.send()
}
func load<T: Decodable>(_ filename: String, as type: T.Type = T.self) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) in main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
func interpretIncoming(data sent: Data) {
do {
let receivedTransmission = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(sent) as! [String: Any]
self.addMessage(message: receivedTransmission["messagePayload"] as! String,
sender: .them,
name: receivedTransmission["messageSender"] as! String)
} catch {
print("FAILED DECODING THING")
}
}
}
Self 在您调用的上下文中不存在。有多种补救方法包括将 interpretIncoming 定义为闭包变量或将其设为 class 方法并根据需要调用。
除了 self
这个词,你问题中的所有内容都是转移注意力的问题。你是说:
class MessageData: ObservableObject, Identifiable {
let subscribe = ... self ...
}
您不能在 属性 声明的初始化程序中提及 self
,因为 self
是我们正在初始化的;还没有self
。
此处的一个简单解决方案可能是将 let subscribe
更改为 lazy var subscribe
,但是您必须在实际代码中询问 subscribe
的值才能获得初始化发生。但是,还有许多其他可能的方法。
刚刚开始掌握 Combine 并遇到一个问题,我需要在我的 class 中调用一个方法,当它从 Publisher
接收到一个值时,在本例中是 Notification
来自 NotificationCenter
...
这是订阅...
let subscribe = NotificationCenter.default.publisher(for: Notification.Name(rawValue: "LocalTalkNotificationReceivedData"), object: nil)
.map( {
([=11=].object as! Data)
} )
.sink(receiveValue: {
self.interpretIncoming(data: [=11=])
})
编译器告诉我的是 Use of unresolved identifier 'self'
。
太晚了,我有点累了,有人知道吗?
Xcode Catalina beta 5 上的 11 beta 5 顺便说一句...
完整文件:
import Foundation
import Combine
import SwiftUI
public class MessageData: ObservableObject, Identifiable {
public var peerData: [Peer] = [Peer]()
public var messageData: [Message] = [Message]()
public var objectWillChange = PassthroughSubject<Void, Never>()
let subscribe = NotificationCenter.default.publisher(for: Notification.Name(rawValue: "LocalTalkNotificationReceivedData"), object: nil)
.map( {
([=12=].object as! Data)
} )
.sink(receiveValue: {
self.interpretIncoming(data: [=12=])
})
init() {
self.setupDummyData()
}
private func setupDummyData() {
self.peerData = self.load("peerData.json")
self.messageData = self.load("messageData.json")
}
func addMessage(message: String, sender: MessageSource, name: String) {
let newMessage = Message(id: Date().hashValue,
content: message,
source: sender,
correspondent: name)
self.messageData.append(newMessage)
self.objectWillChange.send()
}
func load<T: Decodable>(_ filename: String, as type: T.Type = T.self) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) in main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
func interpretIncoming(data sent: Data) {
do {
let receivedTransmission = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(sent) as! [String: Any]
self.addMessage(message: receivedTransmission["messagePayload"] as! String,
sender: .them,
name: receivedTransmission["messageSender"] as! String)
} catch {
print("FAILED DECODING THING")
}
}
}
Self 在您调用的上下文中不存在。有多种补救方法包括将 interpretIncoming 定义为闭包变量或将其设为 class 方法并根据需要调用。
除了 self
这个词,你问题中的所有内容都是转移注意力的问题。你是说:
class MessageData: ObservableObject, Identifiable {
let subscribe = ... self ...
}
您不能在 属性 声明的初始化程序中提及 self
,因为 self
是我们正在初始化的;还没有self
。
此处的一个简单解决方案可能是将 let subscribe
更改为 lazy var subscribe
,但是您必须在实际代码中询问 subscribe
的值才能获得初始化发生。但是,还有许多其他可能的方法。