Swift Combine 通过用户输入更新声明式 UI 从入门到精通十五

时间:2024-02-16 14:48:43
import UIKit import Combine class ViewController: UIViewController { @IBOutlet weak var github_id_entry: UITextField! // 1 var usernameSubscriber: AnyCancellable? // username from the github_id_entry field, updated via IBAction // @Published is creating a publisher $username of type <String, Never> @Published var username: String = "" // 2 // github user retrieved from the API publisher. As it's updated, it // is "wired" to update UI elements @Published private var githubUserData: [GithubAPIUser] = [] // MARK - Actions @IBAction func githubIdChanged(_ sender: UITextField) { username = sender.text ?? "" // 3 print("Set username to ", username) } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. usernameSubscriber = $username // 4 .throttle(for: 0.5, scheduler: myBackgroundQueue, latest: true) // 5 // ^^ scheduler myBackGroundQueue publishes resulting elements // into that queue, resulting on this processing moving off the // main runloop. .removeDuplicates() // 6 .print("username pipeline: ") // debugging output for pipeline .map { username -> AnyPublisher<[GithubAPIUser], Never> in // 7 return GithubAPI.retrieveGithubUser(username: username) } // ^^ type returned by retrieveGithubUser is a Publisher, so we use // switchToLatest to resolve the publisher to its value // to return down the chain, rather than returning a // publisher down the pipeline. .switchToLatest() // 8 // using a sink to get the results from the API search lets us // get not only the user, but also any errors attempting to get it. .receive(on: RunLoop.main) .assign(to: \.githubUserData, on: self) // 9