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

Combine 系列

  1. Swift Combine 从入门到精通一
  2. Swift Combine 发布者订阅者操作者 从入门到精通二
  3. Swift Combine 管道 从入门到精通三
  4. Swift Combine 发布者publisher的生命周期 从入门到精通四
  5. Swift Combine 操作符operations和Subjects发布者的生命周期 从入门到精通五
  6. Swift Combine 订阅者Subscriber的生命周期 从入门到精通六
  7. Swift 使用 Combine 进行开发 从入门到精通七
  8. Swift 使用 Combine 管道和线程进行开发 从入门到精通八
  9. Swift Combine 使用 sink, assign 创建一个订阅者 从入门到精通九
  10. Swift Combine 使用 dataTaskPublisher 发起网络请求 从入门到精通十
  11. Swift Combine 用 Future 来封装异步请求 从入门到精通十一
  12. Swift Combine 有序的异步操作 从入门到精通十二
  13. Swift Combine 使用 flatMap 和 catch错误处理 从入门到精通十三
  14. Swift Combine 网络受限时从备用 URL 请求数据 从入门到精通十四

1. 通过用户输入更新声明式 UI

目的: 查询基于 Web 的 API 并将要显示在 UI 中的数据返回

像 Combine 这样的框架的主要好处之一是建立一个声明性结构,定义界面将如何根据用户输入进行更新。

将 Combine 与 UIKit 集成的模式是设置一个变量,该变量将保持对更新状态的引用,并使用 IBAction 连接控件。

以下示例是更大的 ViewController 实现中的代码的一部分。

这个例子与下一个模式 级联多个 UI 更新,包括网络请求 有点重叠,都建立在一个初始的发布者上。

UIKit-Combine/GithubAPI.swift

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 <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
  1. UITextField 是从用户交互推动更新的界面元素。
  2. 我们定义了一个 @Published 属性,既能保存数据,又能响应更新。 因为它是一个 @Published 属性,它提供了一个发布者,我们可以使用 Combine 的管道更新界面的其他变量或元素。
  3. 我们从 IBAction 内部设置变量 username,如果发布者 $username 有任何订阅者,它反过来就会触发数据流更新。
  4. 我们又在发布者 $username 上设置了一个订阅者,以触发进一步的行为。 在这个例子中,它使用更新过的 username 的值从 Github 的 REST API 取回一个 GithubAPIUser 实例。 每次更新用户名值时,它都会发起新的 HTTP 请求。
  5. throttle 在这里是防止每编辑一次 UITextField 都触发一个网络请求。 throttle 操作符保证了每半秒最多可发出 1 个请求。
  6. removeDuplicates 移除重复的更改用户名事件,以便不会连续两次对相同的值发起 API 请求。 如果用户结束编辑时返回的是之前的值,removeDuplicates 可防止发起冗余请求。
  7. map 在此处和 flatMap 处理错误类似,返回一个发布者的实例。 在 map 被调用时,API 对象返回一个发布者。 它不会返回请求的值,而是返回发布者本身。
  8. switchToLatest 操作符接收发布者实例并解析其中的数据。 switchToLatest 将发布者解析为值,并将该值传递到管道中,在这个例子中,是一个 [GithubAPIUser] 的实例。
  9. 在管道末尾的 assign 是订阅者,它将值分配到另一个变量:githubUserData

模式 级联多个 UI 更新,包括网络请求 在此代码上扩展为各种UI元素的多个级联更新。

参考

https://heckj.github.io/swiftui-notes/index_zh-CN.html

代码

https://github.com/heckj/swiftui-notes

相关推荐
涵涵(互关)17 小时前
Naive-ui树型选择器只显示根节点
前端·ui·vue
我是谁的程序员19 小时前
Mac 上生成 AppStoreInfo.plist 文件,App Store 上架
后端·ios
测试员周周20 小时前
【Appium 系列】第13节-混合测试执行器 — API + UI 的协同执行
开发语言·人工智能·python·功能测试·ui·appium·pytest
莽夫搞战术20 小时前
【Google Stitch】AI原生画布重新定义设计,让想法变成可交互界面
前端·人工智能·ui
sweet丶20 小时前
微信Matrix 卡顿监控原理梳理与图解
ios
2501_916007471 天前
iOS开发中抓取HTTPS请求的完整解决方法与步骤详解
android·网络协议·ios·小程序·https·uni-app·iphone
ZC跨境爬虫1 天前
跟着 MDN 学CSS day_3:(为一个传记页面添加样式)
前端·javascript·css·ui·音视频·html5
UI设计兰亭妙微1 天前
兰亭妙微|打破色彩对比度迷思:UI设计公司中的无障碍设计灵活之道
ui·b端界面设计·高端网站设计
ZZH_AI项目交付1 天前
我把 AI 最容易改坏真实 App 的地方,整理成了 skills
人工智能·ios·app
轻口味1 天前
HarmonyOS 6.1 全栈实战录 - 14 渲染树透镜:FrameNode 渲染状态感知与高性能 UI 调优实战
ui·华为·harmonyos