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

news2024/11/26 11:38:18

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1449079.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

证明之缺角正方形网格的铺地砖问题

缺角正方形网格的铺地砖问题 “挑战难题&#xff1a;多米诺骨牌与无法覆盖的方格” 这里有个著名的难题。画八横八纵正方形网格&#xff0c;去掉相对的两个角。你能用多米诺骨牌形状的地砖——每一块正好覆盖两个相邻方格&#xff0c;把剩余部分覆盖吗&#xff1f;我在下图中…

bert-vits2本地部署报错疑难问题汇总

环境&#xff1a; bert-vits2.3 win 和wsl 问题描述&#xff1a; bert-vits2本地部署报错疑难问题汇总 解决方案&#xff1a; 问题1: Conda安装requirements里面依赖出现ERROR: No matching distribution found for opencc1.1.6 解决方法 需要在 Python 3.11 上使用 Op…

Springboot加载bootstrap和application原理

Springboot加载bootstrap和application原理 bootstrap.yml能被springboot加载导入依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.6</version><rel…

StringBuilder

StringBuilder代表可变字符串&#xff0c;相当于一个容器&#xff0c;里面的字符串可以改变&#xff0c;用来操作字符串。此类设计用作StringBuffer替代品。 构造方法&#xff1a; StringBuilder() StringBuilder(String str) 操作方法&#xff1a; 1. append()&#xff1…

【Spring】定义过滤器Filter和拦截器Interceptor

# 定义过滤器 package com.holen.filter;import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import java.io.IOException;pub…

2048游戏C++板来啦!

个人主页&#xff1a;PingdiGuo_guo 收录专栏&#xff1a;C干货专栏 大家好呀&#xff0c;我是PingdiGuo_guo&#xff0c;今天我们来学习如何用C编写一个2048小游戏。 文章目录 1.2048的规则 2.步骤实现 2.1: 初始化游戏界面 2.1.1知识点 2.1.2: 创建游戏界面 2.2: 随机…

【开源】基于JAVA+Vue+SpringBoot的班级考勤管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统基础支持模块2.2 班级学生教师支持模块2.3 考勤签到管理2.4 学生请假管理 三、系统设计3.1 功能设计3.1.1 系统基础支持模块3.1.2 班级学生教师档案模块3.1.3 考勤签到管理模块3.1.4 学生请假管理模块 3.2 数据库设…

VS Code主题设置(美化VS Code)(主题+背景+图标+特效+字体)

目录 切换整体主题&#xff08;整体主题&#xff09; 切换文件图标主题 设置VS Code背景图案 字体特效 连击特效 字体设置 主题的具体效果放在了文章末尾&#xff0c;这篇文章后续也会进行更新 ————————————————————————————…

Vulnhub靶机:DC3

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;DC3&#xff08;10.0.2.56&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vulnhub.com/entry/dc-32,312…

get和set方法太多太臃肿?快使用 lombok

目录 0. lombok 介绍 1. lombok 使用 1.1 创建一个 maven 项目 1.2 在项目中引用依赖 1.3 在 idea 中添加 lombok 插件 1.4 使用 lombok 注解 1.5 Idea 运行报 Lombok requires enables annotation process 错误解决办法 0. lombok 介绍 当我们写一个类时&#xff0c;为了…

EsayExcel文件导入导出

目录 准备工作 监听器类 导入测试 导出测试 上传Excel 下载Excel 混合导出模板导出 headRowNumber(1)&#xff1a;从第几行开始读 准备工作 导入依赖 <!--easyexcel--> <dependency><groupId>com.alibaba</groupId>x<artifactId>easye…

微服务—ES数据同步

目录 数据同步 问题分析 方案1. 同步调用 方案2. 异步通知 方案3. 监听binlog​编辑 各方案对比 案例——利用MQ实现数据同步 步骤1. 导入hotel-admin项目 步骤2. 声明交换机、队列 步骤3. 发送MQ消息 步骤4. 接收MQ消息 步骤5. 测试同步功能 数据同步 elasticsea…

小白学Halcon100例:如何获取物品中心坐标并展示

文章目录 *读入彩色图片*分解彩色图片为三通道*阈值分割*链接*选择特征*提取目标中心*绘制目标中心--*设置线宽为1*创建十字轮廓*清空窗体*设置绘制模式为绘制边缘*显示目标*显示目标中心*读入彩色图片

算法学习——LeetCode力扣回溯篇4

算法学习——LeetCode力扣回溯篇4 332. 重新安排行程 332. 重新安排行程 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一份航线列表 tickets &#xff0c;其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。 所有这些机票…

python 基础知识点(蓝桥杯python科目个人复习计划41)

今日复习内容&#xff1a;动态规划&#xff08;基础&#xff09; 动态规划是一种解决多阶段决策过程中最优化问题的数学方法和算法思想。它通常用于解决具有重叠子问题和最优子结构性质的问题&#xff0c;通常将问题划分为相互重叠的子问题&#xff0c;利用子问题的解来求解原…

机器学习3----决策树

这是前期准备 import numpy as np import pandas as pd import matplotlib.pyplot as plt #ID3算法 #每个特征的信息熵 # target : 账号是否真实&#xff0c;共2种情况 # yes 7个 p0.7 # no 3个 p0.3 info_D-(0.7*np.log2(0.7)0.3*np.log2(0.3)) info_D #日志密度…

一周学会Django5 Python Web开发-Django5 Hello World编写

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计14条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

Cocos2dx-lua ScrollView[一]基础篇

一.ScrollView概述 cocos游戏中ScrollView控件大量使用,95%以上的项目都会使用ScrollView,个别游戏可能全部使用翻页的滑动效果。如果想要精通Cocos的UI开发,精通ScrollView控件非常关键,因此对ScrollView的使用进行总结很有必要。 下文缩写说明:sv = ScrollView, item代…

Python Matplotlib 的学习笔记

Python Matplotlib 的学习笔记 0. Python Matplotlib 简介1. 为什么要用 Matplotlib&#xff1f;2. Matplotlib 基础类详解2-1. Line&#xff08;线&#xff09;2-2. Marker&#xff08;标记&#xff09;2-3. Text&#xff08;文本&#xff09;2-4. Legend&#xff08;图例&…

数据结构实验三 图的深度优先搜索(包含求连通分量)

全屏浏览作者 王群芳 单位 合肥师范学院 以邻接矩阵作存储结构&#xff0c;编写程序对给定的无向图&#xff08;图中包含n个顶点&#xff0c;编号为0至n-1&#xff09;进行深度优先遍历&#xff0c;并在遍历的过程中计算图G的连通分量个数及边的数目。 本题限定在遍历过程中…