Tag: Rxswift

深入研究RxSwift中的一次性机制。

嘿大家! 作为反应型恋人 ,我将继续撰写有关RxSwift的系列文章。 在我的第一篇反应性文章中,我讲解了flatMap函数的一些改进(您可以在此处进行检查),今天我想通过探索所有Rx Disposables来扩展RxSwift的知识。 本文将通过简短的解释和用法示例来探索Rx中可用的所有Disposables。 所以,让我们开始吧! 🚀 1. Disposable.Empty 每当您需要满足接口要求并且不需要进行任何资源管理时,此功能就很有用。 在幕后,它使用私有类-NopDisposable (Nop =无操作) Rosberry的Shaggy iOS工程师。 被动式开放源代码爱好者和保留周期检测器🙂 还要检查我有关编程,Twitter和开源项目的电报频道:

RxSwift和警报

这篇博客文章将介绍如何使用RxSwift在iOS应用中创建自定义提醒。 以下是我们的应用程序的两个屏幕截图,以及我们将要查看的警报(即将到来的约会),您可以在屏幕底部看到它: 我们应用程序的用户可以称为患者。 他们下载我们的应用的原因是要在他们所在地区的诊所与特定的物理治疗师预约约会。 我们打算使他们的工作变得非常简单。 用户预订约会后,我们会将其带回主屏幕(您可以在上面看到的应用程序的第一个屏幕),然后向他们显示警报,其中提供了即将到来的约会的详细信息。 如果用户点击主屏幕上的即将到来的约会警报,则会为他们提供约会的其他详细信息,您可以在以下屏幕截图中看到这些信息: 创建将在整个应用程序中使用的任何自定义类型(或视图)时,我想做的第一件事就是创建一个心理检查表: 它应该易于其他开发人员使用 它不应该仅限于手头的特定任务而工作 在将笔放到纸上(手指放到键盘上)之前,映射出用户在所有情况下如何使用这种类型的地图 确定如何执行此操作,首先,我们应该实现一个UIView ,该UIView可以从屏幕底部显示,请记住该类型的用户(您的其他开发人员以及您自己)将如何使用此类型。 从一开始就组织代码,立即实施某些步骤后退一步以清理未使用的代码至关重要。 我们将创建的类型是BottomAlert 。 我们将逐步介绍如何实现此类型,以充分利用RxSwift的优势。 以下三种方法是开发人员可以在此类型上使用的唯一方法: 此警报使用了一种不同的UIView类型,我们将其称为ReviewYourLastAppointmentView ,该类型使用枚举和不同的发布主题来处理上述情况: 最后,我想指出这段代码中的某些地方,我们可以充分利用RxCocoa的优势,这将使这些类型的使用更加容易 。 在以后的博客文章中,我将详细介绍如何重构它以充分利用RxCocoa。 最初发布在 gist.github.com上 。

避免RxSwift内存泄漏

我最近对RxSwift的优雅充满热情。 我仍在学习使用RxSwift的越来越好的方法,在这篇简短的文章中,我将分享一些我所学到的避免内存泄漏的知识。 我希望这些指针对那些可能遇到相同问题并寻求解决方案的人有用。 首先,有一点背景。 在我们的项目中,我们使用模型视图呈现器(MVP)架构,其中呈现器具有关于UI如何响应输入以及处理与模型对象的所有交互的所有逻辑。 演示者与视图和模型交互,但是模型和视图不直接交互。 注意,视图≠视图控制器。 在我们的项目中,视图是由视图控制器实现的协议,用于向演示者公开特定的接口。 因此,演示者必须同时引用视图和演示者。 该视图对演示者有很强的参考力,因此可以在加载视图后向演示者注册自己,以便在视图卸载后可以释放演示者。 因此,演示者必须对该视图有较弱的引用,以避免保留周期。 我们在项目中创建的每个视图都将在viewDidLoad()末尾调用其演示者进行注册。 演示者可以在此订阅UI中的可观察对象,并可以绑定到UI控件。 这是一个视图控制器向其演示者注册的示例: 演示者的registerView()方法将以一种非常声明性的方式定义所有UI逻辑。 这是一个部分示例: 难题#1-函数参数 在这里,您可以看到演示者如何要求模型使用URL提取图像,以及Observable使用活页夹将Observable绑定到视图中的UIImageView 。 但是,示例代码已经存在问题。 在bind(to: createPostView.posterImageBinder) , createPostView参数是对该视图的强引用。 由于该视图对演示者有很强的参考作用,因此从一开始就存在一个保留周期。 视图,演示者和模型将在视图卸载后保留在内存中。 更糟糕的是,下次加载该视图时,将创建并保留这三个视图的另一个副本。 但是,有一个简单而优雅的解决方案,即使用局部变量作为在弱变量中捕获视图的方法。 现在,对该视图的引用很少,并且没有保留周期。 难题#2-实例变量 这是有时会出现的另一种有问题的模式: 在上面的代码中有两个问题。 让我们解决第一个问题。 在flatMapLatest { self.createPostModel.createPost(text: $0, image: $1) }行中,没有显式self不会编译实例变量,这将与presenter和闭包创建一个保留周期。 我们可以使用另一个局部常量来解决此问题,以获取模型参考而不引用self。 看起来像这样: 难题#3-函数参考 上面的代码中仍然存在一个严重的问题,它将在视图和演示者之间创建一个保留周期。 你能发现吗? 它在subscribe(onNext: view.pop) 。 这是微妙的。 事实证明,如果在Swift中使用函数引用,则编译器会创建一个对要在其上执行函数的实例的强引用。 因此,即使view变量本身被声明为weak,使用view.pop仍会创建对view的强引用。 有趣的是,使用view.pop()将具有弱引用。 也许将来的Swift版本会解决这个问题。 在撰写本文时,Swift 4.2在使用函数引用语法时正在捕获强大的引用。 […]

像老板一样进行测试— RxSwift简介

在此处阅读全文 在最近的几篇文章中,我们一直在研究Streams –随时间变化的值。 掌握起来并不是很困难,我们一直在努力将它们集成到View Model中。 硬币的另一面虽然正在测试我们的代码。 我们如何使用RxSwift测试反应式代码? 我们使用一个名为RxTest的库。 RxTest使我们可以访问测试计划程序。 调度程序就像一件工作,通常我们将在特定线程上运行它,例如在先前的文章中,我们使用主调度程序实例将后台工作移至主线程上。 这里唯一的问题是序列添加到Rx思维方式的同一件事:时间本身。 流可以随时接收事件,因此,为了模拟我们只是伪造它们出现的时间,但是我们对顺序进行了具体说明。 更好的是,我们有一个网络呼叫需要20秒,我们可以伪造20秒而不必等待那么长时间的嘲笑。 考虑带有Rx的视图模型的一种好方法是输入需要提供的输入以及它们将产生的输出。 自然,我们想在此处测试输出,但是输入可能是搜索栏的文本值,这会触发网络调用,并且视图模型会公开我们可以测试的输出值。 它可能是结果列表,或者在这种情况下是String。 现在,让我们看一下如何进行视觉测试: 如你看到的。 视图模型具有输入和输出,这两个输入和输出都可以通过某种方式使数据突变。 就像工厂一样,数据被“绑定”到其中,它被更改并在最后创建一个可观察的对象作为输出,除了我们想在最后订阅该输出。 让我们看一个例子: 在测试目标中,请确保导入RxSwift,RxTest以及项目的@testable导入,以访问其视图模型和其他类似的类: 导入XCTest 导入RxSwift 导入RxTest @testable导入YourAppName 类YourAppName:XCTestCase { 我仅在此项目中使用CocoaPods,但您需要分别导入RxSwift和RxTest。 类ViewModel { //这是我们将向其发送输入的公共属性。 也许这可能是搜索栏的文本或标签的文本值。 公共变量输入:BehaviorSubject = BehaviorSubject (值:“”) //这是我们将测试的输出值 惰性var输出:BehaviorSubject = BehaviorSubject (值:“”) 让disposeBag = DisposeBag() //简单的初始化即可自动自动调用我们的订阅 在里面() { setupBindings() } //订阅更改的简单函数 私人功能setupBindings(){ input.subscribe(onNext:{[弱自我]值 self?.output.onNext(“更改的\(值)”) } […]

RxSwift简介:iOS开发人员需要吗?

目前,要开发出色的应用程序,需要编写代码,以同时处理用户交互,执行网络操作,管理数据,呈现动态内容等。 这意味着要编写大量异步和并发代码,这可能很难正确解决,甚至难以维护。 这就是响应式编程(特别是响应式扩展)的出现的地方。Swift和iOS的响应式扩展允许编写简洁,易于遵循且灵活的异步和并发代码。 在移动应用程序开发中,Rx相信将带来应用程序开发的重大转变。 尽管许多开发人员发现RxSwift不成熟,因为与其他可用的swift库相比,它是新方法。 但是,那些已经尝试使用这个新的iOS库的人发现,它是处理Swift中难以处理的异步代码的正确解决方案。 使用RxSwift编写可以为Swift编程语言带来全新的体验。 什么是RXSwift? RxSwift是Reactive编程的快速版本。 响应式编程由于其独特的编程范式可以自动更改与控制应用程序性能的更改相关的所有变量,因而具有巨大的意义。 响应式编程是指定义如何对更改(例如用户输入,来自流的数据,系统状态的更改等)做出反应的编程。 RxSwift库是具有反应性扩展的Swift语言版本,就像其他语言(如RxJava,RxJs,Rx.Net等)中提供的一样。它的过程异步代码易于在后台执行,而不会干扰用户设备上的UI和UX体验。 它是Swift中最期待的解决方案,即使用可观察的序列组成异步和基于事件的程序。 “可观察”可以用作通用的,高度可组合的模式。 因此,开发人员不再需要立即使用大量模式,包括完成块,委派,目标动作等。 让我们了解RxSwift实际解决的特定问题。 总而言之,RxSwift允许以声明式方式进行应用程序开发,因此您可以在以下情况下使用它: 被KVO打扰 KVO(键值观察)是在Objective-C中执行的一种实践,它允许向对象通知其他对象状态的特定变化。 尽管KVO具有强大的功能,但由于多种原因,它在程序员中并不那么受欢迎,而是它的显着缺点,即频繁使用时会消耗性能。 另一方面,RxSwift提供了解决方案。 通过最大限度地减少涉及此API的必要性,从根本上迅速地进行了反应式扩展。 您需要同步两个请求。 在许多情况下,开发人员必须调用有助于重新设计当前UI表示形式的API。 这是必需的,因为并非所有REST API都适合为移动平台构建应用程序。 开发人员必须牢记许多布尔变量,并建立一个有助于处理变量互连性的类。 当开发人员使用RxSwift时,它使他们可以结合两个可观察对象并在处理两个API请求结束时发送答案。 您不喜欢与代表同行。 UI开发是必不可少的,因为它会对各种异步任务做出反应。 在Swift中,这些模板称为委托。 委托的作用是使开发人员能够通过异步调用解决问题。 开发人员必须为此编写大量的代码,这需要团队付出巨大的努力,因为使用委托人需要大量的信息。 在这里,RxSwift消除了使用大量委托的严格必要性。 此框架允许进行声明式编码,该编码不会影响UIViewController的大小,并且不再需要objc。 开发人员不必进行繁琐且不负责任的工作,而可以轻松地使代码清晰。 您可能需要编写自己的可观察的东西 在应用程序开发过程中,开发人员需要创建自己的可观察对象时,这是正常现象。 RxSwift在这里非常容易。 使用此框架,开发人员可以轻松地用URLSession包装HTTP请求。 结论:使用Swift进行反应式编程 如我们所见,在专业应用程序开发服务中应用反应式编程可以解决复杂的问题并构建有效的程序。 它会自动加快开发过程,并帮助开发人员专注于可扩展的应用程序。 因此,每个iOS开发人员都应在iPhone和iPad应用程序开发过程中尝试此新扩展。

iOS:Swift中的依赖注入

在上一篇文章中,我们有机会从概念上定义应用程序的体系结构。 这篇文章的目的是深入了解我们正在使用的该体系结构的关键组件的实现。 在这篇文章中,我们将讨论如何实现: 依赖注入 我认为James Shore的这段话定义了依赖注入是什么: 依赖注入意味着给对象一个实例变量。 真。 而已。 依赖注入是一种软件设计模式,可以帮助您使代码更具可测试性,从而减少耦合。 习惯性依赖注入模式面临单例模式。 我认为,根据我作为iOS开发人员的经验,我建议在大多数情况下使用依赖项注入模式,因为除其他外,它在测试期间隔离类非常方便。 尽管这两种模式在每种情况下均有效,但是由于项目的某些组件在某些访问模式下可以更好地工作。 有一些替代方案,例如Swinject,可以在项目中实现依赖项注入,但是在向项目添加新的依赖项之前,我们希望向我们提出一个关键问题:确实有必要吗? 我们可以解决这种需求而无需添加第三方依赖项吗? 在这种情况下,我们认为可以,可以! 我们意识到我们实际上并不需要任何外部库,这就是为什么…… 让我们以应用程序中一个常见情况的示例开始实施: 您有一个带有Presenter的UIViewController。 该Presenter需要一个对象来填充视图,并具有从存储库中获取数据的用例。 我们的建议是定义一个带有一系列方法的协议,这些方法将接收返回准备使用的实例所需的所有实例变量。 我们将此协议命名为Assembler 。 注意,我们需要初始化用例存储库,以将用例注入演示者。 现在,我们可以使用此协议来实例化UIViewController: 结论 使用这些汇编程序来解析程序依赖性的优点是: 没有第三方依赖性。 输入解决依赖性所需的参数,因此开发人员不会犯错误。 要实例化一个组件,您需要解决其依赖性,这可以保证其行为良好。 该应用程序的每个组件都是分离的,可以进行注入模拟测试。 帮助您避免使用共享实例。 (…或至少让​​您考虑是否必要) 希望您发现这篇文章有趣并且对您的项目有用。 任何问题或评论都将受到欢迎! 谢谢,祝你好运! 相关文章 在以下文章中,我们详细介绍了架构中的其他关键组件: Tiendeo应用程序中的MVP清洁架构 RxSwift +干净的架构 储存库模式 这个实现受到了这篇文章的启发。

数据绑定的观察者模式的实现。

很多人可能听说过RxSwift —一种功能性反应式编程(FRP)框架。 它包含与处理数据流相关的大量功能,例如转换,过滤,将一个合并到另一个以及更多。 但是,如果您的项目不需要所有功能,而您只想对某些价值的变化做出反应,那么观察者模式就是您的首选解决方案! 今天,我将向您展示此模式的实现,它的应用以及作为奖励,如何以声明方式将可观察的值绑定到UI。 观察者模式有两个主要角色: Publisher-产生指示值已更改的事件的对象 观察者-对那些事件做出反应的对象。 首先,我们将专注于发布者类型,我们将其称为Variable 。 这将是带有通用参数E的类,该类指示观察值的类型。 我们来看一下Variable的接口。 它已指定将初始值设置为_value属性的初始化程序。 接下来,有两种主要方法: setValue(_:) —它将新值设置为_value属性,并通过使用新值调用所有观察者来通知类型(E) -> Void的所有观察者。 subscribe(_:) —将新的观察者添加到观察者数组中。 现在,我们可以使用Variable ,如下所示: 在这种情况下, Publisher是一个variable对象,而Observer是一个闭包,我们将其传递给subscribe(_:)方法。 现在,我们的发布者类型似乎很有用,但它缺乏非常重要的功能- 价值 转换 。 为此,我们将定义map(_:)方法。 顺便说一句,添加此方法将使Variable成为函子! 如果您对此概念感到好奇,请参阅Wiki。 这使我们可以进行如下操作: 控制台输出: Test Test-transformed 奖金部分 还记得我曾经说过的,您将可以将可观察的值绑定到UI吗? 干得好! 为此,我们将定义一个Bindable协议。 接下来,我们将添加一个自定义运算符 。 我们将其称为bind因为如果使用它可实现Bindable协议,我们会将Variable绑定到其他对象。 它只是bind(_:) Binder bind(_:)方法订阅到Variable 。 让我们使UILabel符合Bindable以启用绑定! 现在,变量绑定就像这样: 而已! 随时发表评论。 完整的源代码位于GitHub。您可以通过LinkedIn或Facebook与我联系。

[RxSwift]观察员

안쓰냐고요?。? 네观察员입니다。 (단호) 观察者 。다。 可观察的도큐멘트로가보면렇게이써있다。 ReactiveX观察者可观察到的。 观察者observable이이이템(들)에다。 observer기서세가지,바로观察者,可观察的그리고subscription(구독)。 자,쓰이시작해시작해보시작해。 위의订阅함수는ObservableType의扩展名런식으이런식으로정의다。 옵저버는만들어지는걸까..옵저버는observable을订阅있었다있었다。 2.观察者대한订阅 이코드가의미하는것은。 우선asObservable은ObservableType의扩展의정의되어다。 Ob로ObservableType을Observable변환해준다는다。 붙는.subscribe(observer)는? serv것도serv serv있는协议serv serv serv serv serv다。 。기본적으로형태를보면이러하다。 안에订阅의해정다형태이다。 해당订阅。다같다。 이위해스에서의이받위해기위해观察者구독한다。 문법 * 0位用户已选择“ Next”(另一位)观察者。 *错误나已完成이시퀀가시퀀스는스아무런지않는다않는다。 이동시에이각기다른스있있지만 리소스관리 *完全错误完全错误完全错误。 *订阅에서에서를다호출한의해해해해하하를를。 값 订阅,“观察者”订阅。 자다다다다다보됐는데。 그러니까观察者대한대한订阅을다거다。 형태리고(一次性)써있다。 다시보자。 그러니까 self.asObservable()。subscribe(观察者) 观察者观察者观察者一次性观察者。 。스트에서이있。이있다。 실제코드를보면 观察者,观察者,观察者,观察者!!!! 观察者观察者观察者观察者订阅观察者订阅。

具有RxSwift的自动完成组件

反应式编程为代码重用提供了很大的机会。 使用RxSwift花费的时间越多,对我来说,将某些行为封装在可以在不同流程中使用的组件中就越直观。 我称它们为“ Rx组件”,既没有革命性也没有惊人的意义。 只是划分和征服Rx代码库的一种方法。 如果您想阅读其他人关于Rx世界的想法,请与我在一起-我们将构建Autocomplete功能。 我所谓的“接收组件”只是一个概念。 没有符合协议,也没有子类。 这是一般的插图: 对于其他开发人员,该组件是一个黑匣子 ,只有输入和输出要插入。 输入和输出在数量上是独立的。 组件实现行为 ,这是应用程序中的一个用例。 仅举几个例子: 自动完成功能—该组件接受简单的文本输入,并提供三个输出: 预测 , 错误和加载状态 (即网络调用或数据库查询)。 表格-接受多个不同类型的输入 。 提供相同数量的输出,每个输出针对相应的输入发出验证结果 。 验证结果可能包含描述数据错误的消息。 分页—接受具有给定索引的页面的输入,发出信号告知何时获取更多页面,并发出信号要求刷新第一页 。 加载状态输出是网络活动的简单指示。 每次组件获取新页面时, 页面输出都会发出整个已知页面集。 每个组件都应隔离,并且不可知 。 通过更改我们编排输出的方式,两者都使其可在不同的屏幕上重用。 一个示例可能是将分页组件的输出加载为在不同屏幕上转换为稍有不同的“等待”体验。 一旦我们构建了组件,就应该很容易对其进行单元测试 。 为了使其无缝,请确保所有依赖项都已被协议很好地抽象。 Rx Component 是一个黑匣子 ,只有输入和输出要插入。 它应该被隔离并不可知,以通过更改我们编排输出的方式使其在不同的屏幕上可重用。 希望您有主要想法。 如果没有,那没关系,我将逐步Autocomplete 在 RxSwift中构建Autocomplete 组件的 RxSwift 证明这一点。 这是我们将要构建的体验(请注意,活动期间状态栏中会显示加载指示器): 在Swift中也一样: 我的Rx组件是类 。 通常,它们符合某种用于依赖项注入的协议( AutocompleteType […]