将 @State 转换为 Publisher
Convert a @State into a Publisher
我想将 @State
变量用于 UI 和计算值。
例如,假设我有一个 TextField
绑定到 @State var userInputURL: String = "https://"
。我如何获取 userInputURL
并将其连接到发布者,以便我可以 map
将其转换为 URL
.
伪代码:
$userInputURL.publisher()
.compactMap({ URL(string: [=10=]) })
.flatMap({ URLSession(configuration: .ephemeral).dataTaskPublisher(for: [=10=]).assertNoFailure() })
.eraseToAnyPublisher()
最新的测试版改变了变量的发布方式,所以我认为您根本不想尝试。制作 ObservableObject 类 非常简单,但您随后想要添加一个发布者供您自己使用:
class ObservableString: Combine.ObservableObject, Identifiable {
let id = UUID()
let objectWillChange = ObservableObjectPublisher()
let publisher = PassthroughSubject<String, Never>()
var string: String {
willSet { objectWillChange.send() }
didSet { publisher.send(string) }
}
init(_ string: String = "") { self.string = string }
}
您使用 @ObservableObject
而不是 @State
变量,并记住直接访问 属性 字符串而不是使用 @State 使用的魔法。
您不能将@state 转换为发布者,但您可以改用 ObservableObject。
import SwiftUI
final class SearchStore: ObservableObject {
@Published var query: String = ""
func fetch() {
$query
.map { URL(string: [=10=]) }
.flatMap { URLSession.shared.dataTaskPublisher(for: [=10=]) }
.sink { print([=10=]) }
}
}
struct ContentView: View {
@StateObject var store = SearchStore()
var body: some View {
VStack {
TextField("type something...", text: $store.query)
Button("search") {
self.store.fetch()
}
}
}
}
您还可以使用 onChange(of:)
响应 @State
更改。
struct MyView: View {
@State var userInputURL: String = "https://"
var body: some View {
VStack {
TextField("search here", text: $userInputURL)
}
.onChange(of: userInputURL) { _ in
self.fetch()
}
}
func fetch() {
print("changed", userInputURL)
// ...
}
}
输出:
changed https://t
changed https://ts
changed https://tsr
changed https://tsrs
changed https://tsrst
我想将 @State
变量用于 UI 和计算值。
例如,假设我有一个 TextField
绑定到 @State var userInputURL: String = "https://"
。我如何获取 userInputURL
并将其连接到发布者,以便我可以 map
将其转换为 URL
.
伪代码:
$userInputURL.publisher()
.compactMap({ URL(string: [=10=]) })
.flatMap({ URLSession(configuration: .ephemeral).dataTaskPublisher(for: [=10=]).assertNoFailure() })
.eraseToAnyPublisher()
最新的测试版改变了变量的发布方式,所以我认为您根本不想尝试。制作 ObservableObject 类 非常简单,但您随后想要添加一个发布者供您自己使用:
class ObservableString: Combine.ObservableObject, Identifiable {
let id = UUID()
let objectWillChange = ObservableObjectPublisher()
let publisher = PassthroughSubject<String, Never>()
var string: String {
willSet { objectWillChange.send() }
didSet { publisher.send(string) }
}
init(_ string: String = "") { self.string = string }
}
您使用 @ObservableObject
而不是 @State
变量,并记住直接访问 属性 字符串而不是使用 @State 使用的魔法。
您不能将@state 转换为发布者,但您可以改用 ObservableObject。
import SwiftUI
final class SearchStore: ObservableObject {
@Published var query: String = ""
func fetch() {
$query
.map { URL(string: [=10=]) }
.flatMap { URLSession.shared.dataTaskPublisher(for: [=10=]) }
.sink { print([=10=]) }
}
}
struct ContentView: View {
@StateObject var store = SearchStore()
var body: some View {
VStack {
TextField("type something...", text: $store.query)
Button("search") {
self.store.fetch()
}
}
}
}
您还可以使用 onChange(of:)
响应 @State
更改。
struct MyView: View {
@State var userInputURL: String = "https://"
var body: some View {
VStack {
TextField("search here", text: $userInputURL)
}
.onChange(of: userInputURL) { _ in
self.fetch()
}
}
func fetch() {
print("changed", userInputURL)
// ...
}
}
输出:
changed https://t
changed https://ts
changed https://tsr
changed https://tsrs
changed https://tsrst