将@state转换为发布者



我想在UI和计算值的情况下使用@State变量。

例如,假设我有一个 TextField绑定到 @State var userInputURL: String = "https://"。我将如何使用userInputURL并将其连接到发布者,以便我可以将其 map CC_5。

伪代码:

$userInputURL.publisher()
      .compactMap({ URL(string: $0) })
      .flatMap({ URLSession(configuration: .ephemeral).dataTaskPublisher(for: $0).assertNoFailure() })
      .eraseToAnyPublisher()

您不能将@state转换为发布者,但是您可以使用ObservableObject。

import SwiftUI
final class SearchStore: ObservableObject {
    @Published var query: String = ""
    func fetch() {
        $query
            .map { URL(string: $0) }
            .flatMap { URLSession.shared.dataTaskPublisher(for: $0) }
            .sink { print($0) }
    }
}
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

最新的beta改变了变量的发布方式,因此我认为您什至不想尝试。进行可观察的对象类非常容易,但是您想添加出版商以供自己使用:

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使用的魔法。

iOS 14.0后,您可以访问发布者。

struct MyView: View {
    @State var text: String?
    
    var body: some View {
        Text(text ?? "")
            .onReceive($text.wrappedValue.publisher) { _ in
                let publisher1: Optional<String>.Publisher = $text.wrappedValue.publisher
                
                // ... or
                
                let publisher2: Optional<String>.Publisher = _text.wrappedValue.publisher
            }
    }
}

相关内容

  • 没有找到相关文章

最新更新