Swift Combine 通过用户输入更新声明式 UI 从入门到精通十五
Combine 系列
- Swift Combine 从入门到精通一
- Swift Combine 发布者订阅者操作者 从入门到精通二
- Swift Combine 管道 从入门到精通三
- Swift Combine 发布者publisher的生命周期 从入门到精通四
- Swift Combine 操作符operations和Subjects发布者的生命周期 从入门到精通五
- Swift Combine 订阅者Subscriber的生命周期 从入门到精通六
- Swift 使用 Combine 进行开发 从入门到精通七
- Swift 使用 Combine 管道和线程进行开发 从入门到精通八
- Swift Combine 使用 sink, assign 创建一个订阅者 从入门到精通九
- Swift Combine 使用 dataTaskPublisher 发起网络请求 从入门到精通十
- Swift Combine 用 Future 来封装异步请求 从入门到精通十一
- Swift Combine 有序的异步操作 从入门到精通十二
- Swift Combine 使用 flatMap 和 catch错误处理 从入门到精通十三
- Swift Combine 网络受限时从备用 URL 请求数据 从入门到精通十四
1. 通过用户输入更新声明式 UI
目的: 查询基于 Web 的 API 并将要显示在 UI 中的数据返回
像 Combine 这样的框架的主要好处之一是建立一个声明性结构,定义界面将如何根据用户输入进行更新。
将 Combine 与 UIKit 集成的模式是设置一个变量,该变量将保持对更新状态的引用,并使用 IBAction 连接控件。
以下示例是更大的 ViewController 实现中的代码的一部分。
这个例子与下一个模式 级联多个 UI 更新,包括网络请求 有点重叠,都建立在一个初始的发布者上。
UIKit-Combine/GithubAPI.swift
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 @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 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
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理!
部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理!
图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!