Swift Combine 使用 print 操作符调试管道 从入门到精通二十四

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 请求数据 从入门到精通十四
  15. Swift Combine 通过用户输入更新声明式 UI 从入门到精通十五
  16. Swift Combine 级联多个 UI 更新,包括网络请求 从入门到精通十六
  17. Swift Combine 合并多个管道以更新 UI 元素 从入门到精通十七
  18. Swift Combine 通过包装基于 delegate 的 API 创建重复发布者 从入门到精通十八
  19. Swift Combine 响应NotificationCenter 的更新 从入门到精通十九
  20. Swift Combine 使用 ObservableObject 与 SwiftUI 模型作为发布源 从入门到精通二十
  21. Swift Combine 使用 XCTestExpectation 测试发布者 从入门到精通二十一
  22. Swift Combine 使用 PassthroughSubject 测试订阅者 从入门到精通二十二
  23. Swift Combine 使用从 PassthroughSubject 预定好的发送的事件测试订阅者 从入门到精通二十三
    在这里插入图片描述

1. 使用 print 操作符调试管道

目的:为了了解管道中正在发生的事情,查看所有控制事件和数据交互。

我获取的最详细的信息来自有选择地使用 print 操作符。 缺点是它打印了大量信息,因此输出可能很快变得非常庞大。 要理解简单的管道,使用 .print() 作为没有任何参数的操作符是非常简单的。 一旦你想要添加多个 print 操作符,你可能要使用 string 参数,该参数会作为前缀放在输出中。

示例 级联多个 UI 更新,包括网络请求 在几个地方都有用到它,使用比较长的描述性前缀,以明确是哪个管道在提供信息。

通过连接到一个私有的 @Published 的变量 —— githubUserData,两个管道被层叠到了一起。 该示例代码中的两个相关管道:

UIKit-Combine/GithubViewController.swift

usernameSubscriber = $username.throttle(for: 0.5, scheduler: myBackgroundQueue, latest: true)// ^^ scheduler myBackGroundQueue publishes resulting elements// into that queue, resulting on this processing moving off the// main runloop..removeDuplicates().print("username pipeline: ") // debugging output for pipeline.map { username -> AnyPublisher<[GithubAPIUser], Never> inreturn GithubAPI.retrieveGithubUser(username: username)}// ^^ type returned in the pipeline is a Publisher, so we use// switchToLatest to flatten the values out of that// pipeline to return down the chain, rather than returning a// publisher down the pipeline..switchToLatest()// 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)// using .assign() on the other hand (which returns an
// AnyCancellable) *DOES* require a Failure type of <Never>
repositoryCountSubscriber = $githubUserData.print("github user data: ").map { userData -> String inif let firstUser = userData.first {return String(firstUser.public_repos)}return "unknown"}.receive(on: RunLoop.main).assign(to: \.text, on: repositoryCountLabel)

当你运行 UIKit-Combine 示例代码时,随着我慢慢的输入用户名 heckj,终端会显示以下输出。 在进行这些查找的过程中,在最终的帐户之前发现并检索到了另外两个 github 帐户(hec 和 heck)。

模拟器的交互输出

username pipeline: : receive subscription: (RemoveDuplicates)
username pipeline: : request unlimited
github user data: : receive subscription: (CurrentValueSubject)
github user data: : request unlimited
github user data: : receive value: ([])
username pipeline: : receive value: ()
github user data: : receive value: ([])Set username to  h
username pipeline: : receive value: (h)
github user data: : receive value: ([])Set username to  he
username pipeline: : receive value: (he)
github user data: : receive value: ([])Set username to  hec
username pipeline: : receive value: (hec)Set username to  heck
github user data: : receive value: ([UIKit_Combine.GithubAPIUser(login: "hec", public_repos: 3, avatar_url: "https://avatars3.githubusercontent.com/u/53656?v=4")])username pipeline: : receive value: (heck)
github user data: : receive value: ([UIKit_Combine.GithubAPIUser(login: "heck", public_repos: 6, avatar_url: "https://avatars3.githubusercontent.com/u/138508?v=4")])Set username to  heckj
username pipeline: : receive value: (heckj)
github user data: : receive value: ([UIKit_Combine.GithubAPIUser(login: "heckj", public_repos: 69, avatar_url: "https://avatars0.githubusercontent.com/u/43388?v=4")])

一些放在 sink 闭包中,用来查看最终结果的无关打印语句已被删除。

你可以在开始时看到初始化订阅的设置,然后看到通知,包括通过 print 操作符传递的值的调试信息。 虽然上面的示例内容中未显示它,但你还会在出现错误时看到取消管道的事件,或在发布者报告没有进一步数据时的 completions 事件。

在操作符两侧使用 print 来了解其具体的操作方式也很有用。

一个这样做的例子如下,利用前缀显示 retry 操作符及其工作原理:

UsingCombineTests/RetryPublisherTests.swift

func testRetryWithOneShotFailPublisher() {// setuplet _ = Fail(outputType: String.self, failure: TestFailureCondition.invalidServerResponse).print("(1)>")  // 1.retry(3).print("(2)>")  // 2.sink(receiveCompletion: { fini inprint(" ** .sink() received the completion:", String(describing: fini))}, receiveValue: { stringValue inXCTAssertNotNil(stringValue)print(" ** .sink() received \(stringValue)")})
}
  1. 前缀 (1) 是显示 retry 操作符上方的交互行为。
  2. 前缀 (2) 是显示 retry 操作符之后的交互行为。

单元测试的输出

Test Suite 'Selected tests' started at 2019-07-26 15:59:48.042
Test Suite 'UsingCombineTests.xctest' started at 2019-07-26 15:59:48.043
Test Suite 'RetryPublisherTests' started at 2019-07-26 15:59:48.043
Test Case '-[UsingCombineTests.RetryPublisherTests testRetryWithOneShotFailPublisher]' started.
(1)>: receive subscription: (Empty) 
(1)>: receive error: (invalidServerResponse)
(1)>: receive subscription: (Empty)
(1)>: receive error: (invalidServerResponse)
(1)>: receive subscription: (Empty)
(1)>: receive error: (invalidServerResponse)
(1)>: receive subscription: (Empty)
(1)>: receive error: (invalidServerResponse)
(2)>: receive error: (invalidServerResponse) ** .sink() received the completion: failure(UsingCombineTests.RetryPublisherTests.TestFailureCondition.invalidServerResponse)
(2)>: receive subscription: (Retry)
(2)>: request unlimited
(2)>: receive cancel
Test Case '-[UsingCombineTests.RetryPublisherTests testRetryWithOneShotFailPublisher]' passed (0.010 seconds).
Test Suite 'RetryPublisherTests' passed at 2019-07-26 15:59:48.054.Executed 1 test, with 0 failures (0 unexpected) in 0.010 (0.011) seconds
Test Suite 'UsingCombineTests.xctest' passed at 2019-07-26 15:59:48.054.Executed 1 test, with 0 failures (0 unexpected) in 0.010 (0.011) seconds
Test Suite 'Selected tests' passed at 2019-07-26 15:59:48.057.Executed 1 test, with 0 failures (0 unexpected) in 0.010 (0.015) seconds
  1. 在测试例子中,发布者总是返回失败,在输出结果中可以看到带有前缀 (1) 的错误信息,然后 retry 操作符触发重新订阅。
  2. 在其中4次尝试(3次"重试")之后,你就会看到从管道中输出的错误。 当错误到达 sink 后,你会看到发出的 cancel 信号,该信号在重试操作符之后停止。

虽然非常有效,但 print 操作符是一个钝器,它会生成大量的输出,你必须分析和审查它们以得到你想要的信息。 如果你想让标识和打印的内容更具选择性,或者如果你需要处理传输的数据才能更有意义地使用它们,那么你可以查看 handleEvents 操作符。 有关如何使用此操作符进行调试的更多详细信息,请查阅 使用 handleEvents 操作符调试管道。

参考

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

代码

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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】每天五分钟,快速入门数据结构(一)——数组

目录 一.初始化语法 二.特点 三.数组中的元素默认值 四.时间复杂度 五.Java中的ArrayList类 可变长度数组 1 使用 2 注意事项 3 实现原理 4 ArrayList源码 5 ArrayList方法 一.初始化语法 // 数组动态初始化&#xff08;先定义数组&#xff0c;指定数组长度&#xf…

【C#】使用代码实现龙年春晚扑克牌魔术(守岁共此时),代码实现篇

欢迎来到《小5讲堂》 大家好&#xff0c;我是全栈小5。 这是《C#》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对知识点的理解和掌握。…

DS:栈和队列的相互实现

创作不易&#xff0c;感谢友友们三连&#xff01;&#xff01; 一、前言 栈和队列的相互实现是用两个栈去实现队列或者是用两个队列去实现栈&#xff0c;这样其实是把问题复杂化的&#xff0c;实际中没有什么应用价值&#xff0c;但是通过他们的相互实现可以让我们更加深入地理…

PyTorch使用Tricks:Dropout,R-Dropout和Multi-Sample Dropout等 !!

文章目录 1、为什么使用Dropout&#xff1f; 2、Dropout的拓展1&#xff1a;R-Dropout 3、Dropout的拓展2&#xff1a;Multi-Sample Dropout 4、Dropout的拓展3&#xff1a;DropConnect 5、Dropout的拓展4&#xff1a;Standout 6、Dropout的拓展5&#xff1a;Gaussian Dropout …

Jest和Mocha对比:两者之间有哪些区别?

什么是单元测试&#xff1f; 所谓单元测试&#xff0c;是对软件中单个功能组件进行测试的一种软件测试方式&#xff0c;其目的是确保代码中的每一个基本单元都能正常运行。因此&#xff0c;开发人员在应用程序开发的整个过程&#xff08;即代码编写过程&#xff09;中都需要进行…

Avalonia学习(二十四)-系统界面

目前项目式练习&#xff0c;界面内容偏多&#xff0c;所以不给大家贴代码了&#xff0c;可以留言交流。此次为大家展示的是物联项目的例子&#xff0c;仅仅是学习&#xff0c;我把一些重点列举一下。 界面无边框 以前的样例主要是通过实现控件来完成的&#xff0c;前面已经有窗…

美团外卖商超药店商品销量

外卖药店商品月销量 外卖商超商品月销量

学习总结19

# 奶牛的耳语 ## 题目描述 在你的养牛场&#xff0c;所有的奶牛都养在一排呈直线的牛栏中。一共有 n 头奶牛&#xff0c;其中第 i 头牛在直线上所处的位置可以用一个整数坐标 pi(0< pi < 10^8) 来表示。在无聊的日子里&#xff0c;奶牛们常常在自己的牛栏里与其它奶牛交…

术业有专攻!三防加固平板助力工业起飞

在日常使用中的商业电脑比较追求时效性&#xff0c;以市场定位做标准&#xff0c;内部元件只需满足一般要求就行&#xff0c;使用寿命比较短。而三防平板电脑是主要运用在复杂、恶劣的环境下所以在需求方面较高,需要保证产品在恶劣条件下正常使用&#xff0c;满足行业领域的需求…

Jakarta Bean Validation

Validation 官网 https://beanvalidation.org/ 常见注解 Bean Validation中定义的注解&#xff1a; 注解详细信息Null被注释的元素必须为 nullNotNull被注释的元素必须不为 nullAssertTrue被注释的元素必须为 trueAssertFalse被注释的元素必须为 falseMin(value)被注释的元素…

【linux】体系结构和os管理

冯诺依曼体系结构 输入单元&#xff1a;包括键盘, 鼠标&#xff0c;扫描仪, 写板等 中央处理器(CPU)&#xff1a;含有运算器和控制器等 输出单元&#xff1a;显示器&#xff0c;打印机等 这里的存储器指的是内存 三者是相互连接的&#xff0c;设备之间会进行数据的来回拷贝&am…

【springboot+vue项目(十五)】基于Oauth2的SSO单点登录(二)vue-element-admin框架改造整合Oauth2.0

Vue-element-admin 是一个基于 Vue.js 和 Element UI 的后台管理系统框架&#xff0c;提供了丰富的组件和功能&#xff0c;可以帮助开发者快速搭建现代化的后台管理系统。 一、基本知识 &#xff08;一&#xff09;Vue-element-admin 的主要文件和目录 vue-element-admin/ |…

人工智能_普通服务器CPU_安装清华开源人工智能AI大模型ChatGlm-6B_001---人工智能工作笔记0096

使用centos安装,注意安装之前,保证系统可以联网,然后执行yum update 先去更新一下系统,可以省掉很多麻烦 20240219_150031 这里我们使用centos系统吧,使用习惯了. ChatGlm首先需要一台个人计算机,或者服务器, 要的算力,训练最多,微调次之,推理需要算力最少 其实很多都支持C…

stable diffusion webui学习总结(2):技巧汇总

一、脸部修复&#xff1a;解决在低分辨率下&#xff0c;脸部生成异常的问题 勾选ADetailer&#xff0c;会在生成图片后&#xff0c;用更高的分辨率&#xff0c;对于脸部重新生成一遍 二、高清放大&#xff1a;低分辨率照片提升到高分辨率&#xff0c;并丰富内容细节 1、先通过…

【LeetCode】树的BFS(层序遍历)精选6题

目录 1. N 叉树的层序遍历&#xff08;中等&#xff09; 2. 二叉树的锯齿形层序遍历&#xff08;中等&#xff09; 3. 二叉树的最大宽度&#xff08;中等&#xff09; 4. 在每个树行中找最大值&#xff08;中等&#xff09; 5. 找树左下角的值&#xff08;中等&#xff09…

票务系统平台架构设计与实现

票务系统是一个复杂的平台&#xff0c;涉及到用户购票、票务管理、支付结算等多方面功能。本文将介绍票务系统平台的架构设计原则、技术选型以及实现过程&#xff0c;帮助读者了解如何构建一个高效、稳定的票务系统。 正文&#xff1a; 1. 系统设计原则 在设计票务系统平台时…

【计算机网络】网络基础

初识网络 一、网络发展二、认识协议三、认识网络协议1. 协议分层2. OSI 七层模型3. TCP/IP五层模型4. OS和网络协议栈 四、网络传输基本流程1. TCP/IP 协议通讯过程2. 以太网通信&#xff08;1&#xff09;以太网通信原理&#xff08;2&#xff09;数据碰撞 3. 数据跨网络传输 …

计算机网络概论和数据通信基础

文章目录 计算机网络概论从物理构成上看&#xff0c;计算机网络包括硬件、软件和协议三大部分计算机网络的功能组成计算机网络的分类网络体系结构分层与体系结构接口、协议和服务数据传送单位OSI模型TCP/IP模型 数据通信基础数字信号调制为模拟信号正交振幅调制QAM 模拟数据编码…

STM32Cubemx TB6612直流电机驱动

一、TB6612FNG TB6612是一个支持双电机的驱动模块&#xff0c;支持PWM调速。PWMA、AIN1、AIN2 为一组控制引脚&#xff0c;PWMA 为 PWM 速度控制引脚&#xff0c;AIN1、AIN2 为方向控制引脚&#xff1b;PWMB、BIN1、BIN2 为一组控制引脚&#xff0c;PWMB 为 PWM 速度控制引脚&…

例40:滚动条的使用

建立一个EXE工程&#xff0c;在窗体上放一个文本框和一个水平滚动条。设置滚动条的最大最小属性分别为&#xff1a;100和1。如图36。 图36 为滚动条的change事件输入代码&#xff1a; Sub Form1_HScroll1_Change(hWndForm As hWnd, hWndControl As hWnd, hNewPos As Long, n…