赞
踩
Combine 系列
目的: 查询基于 Web 的 API 并将要显示在 UI 中的数据返回
像 Combine 这样的框架的主要好处之一是建立一个声明性结构,定义界面将如何根据用户输入进行更新。
将 Combine 与 UIKit 集成的模式是设置一个变量,该变量将保持对更新状态的引用,并使用 IBAction 连接控件。
以下示例是更大的 ViewController 实现中的代码的一部分。
这个例子与下一个模式 级联多个 UI 更新,包括网络请求 有点重叠,都建立在一个初始的发布者上。
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
UITextField
是从用户交互推动更新的界面元素。@Published
属性,既能保存数据,又能响应更新。 因为它是一个 @Published
属性,它提供了一个发布者,我们可以使用 Combine
的管道更新界面的其他变量或元素。IBAction
内部设置变量 username
,如果发布者 $username
有任何订阅者,它反过来就会触发数据流更新。$username
上设置了一个订阅者,以触发进一步的行为。 在这个例子中,它使用更新过的 username
的值从 Github 的 REST API 取回一个 GithubAPIUser 实例。 每次更新用户名值时,它都会发起新的 HTTP 请求。throttle
在这里是防止每编辑一次 UITextField
都触发一个网络请求。 throttle
操作符保证了每半秒最多可发出 1 个请求。removeDuplicates
移除重复的更改用户名事件,以便不会连续两次对相同的值发起 API 请求。 如果用户结束编辑时返回的是之前的值,removeDuplicates
可防止发起冗余请求。map
在此处和 flatMap
处理错误类似,返回一个发布者的实例。 在 map 被调用时,API 对象返回一个发布者。 它不会返回请求的值,而是返回发布者本身。switchToLatest
操作符接收发布者实例并解析其中的数据。 switchToLatest
将发布者解析为值,并将该值传递到管道中,在这个例子中,是一个 [GithubAPIUser]
的实例。assign
是订阅者,它将值分配到另一个变量:githubUserData
。模式 级联多个 UI 更新,包括网络请求 在此代码上扩展为各种UI元素的多个级联更新。
https://heckj.github.io/swiftui-notes/index_zh-CN.html
https://github.com/heckj/swiftui-notes
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。