I want to use a @State variable both for the UI and for computing a value.
For example, let's say I have a TextField bound to @State var userInputURL: String = "https://". How would I take that userInputURL and connect it to a publisher so I can map it into a URL.
Pseudo code:
$userInputURL.publisher()
      .compactMap({ URL(string: $0) })
      .flatMap({ URLSession(configuration: .ephemeral).dataTaskPublisher(for: $0).assertNoFailure() })
      .eraseToAnyPublisher()
You can't convert @state to publisher, but you can use ObservableObject instead.
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()
            }
        }
    }
}
You can also use onChange(of:) to respond to @State changes.
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)
    // ...
  }
}
Output:
changed https://t
changed https://ts
changed https://tsr
changed https://tsrs
changed https://tsrst
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With