Tag: Rxswift

带RxSwift示例的FRP(#1)

如今,Reactive编程对于许多语言的开发人员世界来说并不陌生。 对于此博客,它将专注于Swift和ReactiveX公司的强度库,绝对是RxSwift,它是2年前成长的语言。 如果您已经熟悉FRP的概念,请跳到下一个示例。 关于FRP概念,请深入阅读我之前的2个博客:这个和另一个。 如果您什至没有时间阅读2个我的博客,则以下是一个简短的FRP: 甚至在Swift宣布之前,功能性反应式编程(FRP)与面向对象的编程相比,近年来已获得了极大的普及。 从Haskell到Java语言,您将找到FRP启发的实现。 为什么是这样? 玻璃钢有什么特别之处? 也许最重要的是,如何在Swift中利用这种范例? “功能性反应式编程”是由Conal Elliott创建的编程范例。 他的定义具有非常具体的语义,欢迎您在这里进行探索。 对于更宽松/简单的定义,功能性反应式编程是其他两个概念的组合: 响应式编程 ,其重点是异步数据流,您可以侦听并相应地做出反应。 要了解更多信息,请查看此出色的介绍。 函数式编程 ,它强调通过数学风格的函数进行计算,不变性和表达性,并最大程度地减少了变量和状态的使用。 要了解更多信息,请查看我们的Swift函数式编程教程。 一个例子 值得说明的一个例子表明FRP的效果就像在UITableView和UISearchBar之间组合搜索某物。 首先,我们需要一个podfile来获取所有和您的依赖项: 要完成,我们有以下这些东西: 接下来,UI将如下所示: 这是准备工作,现在让我们编写代码。 假设您想在您的城市中找到一个或多个IT公司。 尽可能多地创建一个虚拟公司。 同样,您可以制作一个API来响应有价值的数据,但是请避免这样做,因为我们不需要而且从不专注于此,因此会花费很多时间。 虚拟数据,例如: var foundCompanies = [String]() 让companyDummy = [“ Apple Inc”,“ Microsoft Co。”,“ Nokia”,“ Yahoo”,“ Snapchat”,“ Twitter”,“ Facebook”,“ Google”,“ Bings”,“ FPT软件”,“ Framgia”] 开始了! 然后,我们将设置扩展表视图的数据源,如下所示: 拖放tableview,searchBar引用: @IBOutlet弱var searchBar:UISearchBar! […]

反跳方法

在重复的用户操作可能导致发生网络请求的情况下,将呼叫反跳非常有用。 问题在于用户的动作可以在短时间内生成许多请求,这在蜂窝网络上的响应速度可能很慢。 场景:用户连续点击按钮,但只接受最后一个,所有先前的请求都被取消。为简单起见,fetchMethod()打印计数器值。 1:延迟后使用Perform Selector: 类ViewController:UIViewController { var计数器= 0 覆盖func viewDidLoad(){ super.viewDidLoad() } @IBAction func tapButton(sender:UIButton){ 计数器+ = 1 NSObject.cancelPreviousPerformRequests(withTarget:self,选择器:#selector(fetchMethod),object:self) self.perform(#selector(fetchMethod),with:self,afterDelay:3.0) } func fetchMethod(){ print(“ fetchMethod:\(counter)”) } } //输出: fetchMethod:1 //单击一次 fetchMethod:4 //单击4次, //但先前的触发器被取消 // cancelPreviousPerformRequests 2:使用DispatchWorkItem: 类ViewController:UIViewController { 私人varendingRequestWorkItem:DispatchWorkItem? 覆盖func viewDidLoad(){ super.viewDidLoad() } @IBAction func tapButton(sender:UIButton){ 计数器+ = 1 endingRequestWorkItem?.cancel() 让requestWorkItem = DispatchWorkItem {self中的[weak […]

使用RxSwift在ViewController之间传递数据

我2年前开始进行iOS开发,从Treehouse,Raywanderlich,objc.io和GitHub学习。我使用委托将数据从一个ViewController传递到另一个ViewController。我们可以使用RxSwift在几行代码中实现相同的任务。根据标准Rx代表文档 Rx是通过Observable接口表示的通用计算抽象。 像原始的Rx一样,RxSwift的目的是实现异步操作和事件/数据流的轻松组合。 KVO观察,异步操作和流都在序列抽象下统一。 这就是为什么Rx如此简单,优雅和强大的原因。 为了从rootViewController上的推送的viewController传递数据,我们可以轻松做到。 我们必须在SelectedDataVC类的ViewController类上传递数据,让我们深入了解一下。 1.使用CocoaPods,Carthage安装RxSwift和RxCocoa 2,在SelectedDataVC中添加变量和可观察变量 私人让selectedVariable =变量(“”) var selectedObserver:Observable { 返回selectedVariable.asObservable() } selectedVariable是具有一些String的初始值的变量。 selectedObserver是Observable which做一些工作,观察者可以对此做出反应。 当用户从SelectedDataVC中选择一些数据时,只需将数据值设置为selectedVariable selectedVariable.value = selectedName 在ViewController类中添加DisposeBag。根据文档: 处理袋用于将类似ARC的行为返回给RX。 当DisposeBag被释放时,它将在每个添加的一次性物品上调用dispose。 现在,当某些用户单击加号图标以在ViewControllerVC中设置数据时,则SelectedDataVC将被推入堆栈。添加以下代码行: 让selectedItemVC = self.storyboard?.instantiateViewController(withIdentifier:“ SelectDataVC”)作为! SelectDataVC selectedItemVC.selectedObserver .subscribe(onNext:{[弱自我] selectedName在 如果selectedName.count> 0 { self?.displayLabel.text = selectedName } } .disposed(作者:disposeBag) self.navigationController?.pushViewController(selectedItemVC,animation:true) 在实例化SelectedDataVC的过程中,我们正在ViewController类中订阅SelectedDataVC的事件,每当selectedVariable值更改时,我们在ViewController类中的标签就会更新。 这是完整的演示代码:https://github.com/EonKid/RxSwiftDemo 感谢您的阅读。如果您有任何疑问,请发表评论。

Swift4中使用MVVM的流程协调器[第1部分]

将所有逻辑嵌入ViewController会导致iOS应用程序开发中一个著名的问题,称为Massive View Controllers。 建筑师和开发人员开始采用新的体系结构来解决此问题。 所采用的一种这样的体系结构是MVVM(Model-View-ViewModel),它已在iOS应用程序开发中非常普遍(与RxSwift结合使用)。 MVVM使您可以取消应用业务逻辑的耦合,并可以测试用例和用户界面。 这导致可重用性和更好地维护代码库。 使用Segue在iOS中可以轻松实现视图控制器之间的导航。 它的易用性和可视化布局可见性将吸引您将所有导航逻辑都包含在视图控制器和情节提要中。 但是从长远来看,这将导致巨大的耦合和可重用性问题。 为了解决此问题,MVVM体系结构中采用的一种更清洁的方法是流程协调器。 协调器是基本的Swift对象,可以封装导航逻辑并使组件可重用。 本教程演示了将现有基于情节提要的代码重构为协调器导航流程的开始步骤。 在本集中,我们将从重构使用基本MVVM构建的现有代码库开始。 我们介绍了Flow协调器,用于将导航逻辑与Segue和ViewController分离开,并将其移至Coordinators。 我们定义了所有协调员都需要遵守的协议,并且协议定义引入了childCoordinators,这让父级协调员拥有一个引用,直到弹出或关闭它们为止。 如果您喜欢这些教程的质量,请喜欢,订阅和分享。 请观看以下链接提供的所有剧集: 第1集-https://youtu.be/fH9paWpCvQs 第2集-https://youtu.be/qLbUzwZrQjc 第3集-https://youtu.be/qLbUzwZrQjc 第4集-https://youtu.be/b1GadsUtB9s 第5集-https://youtu.be/EZtCOQyRK7w 第6集-https://youtu.be/T0yT6J_Mp9U 第7集-https://youtu.be/ur-U9nzazbc 第8集-https://youtu.be/6KC1GdLnez0 第9集-https://youtu.be/fT_VI1SiapQ 第10集-https://youtu.be/KvDd1JTCWC8 第11集-https://youtu.be/PnEOgW7Ccig 观看其他TOP编程教程,网址为: youtube.com/c/letscodeeasy 请关注我们: http://letscodeeasy.com www.facebook.com/letscodeeasy https://twitter.com/letscodeeasy

单元测试RxSwift应用程序

我今天要谈论的主题是RxSwift应用程序的单元测试。 这是我的系列文章“如何在MVVM中使用RxSwift”的最后一部分,在该系列中,我们通过实现Friends应用程序学习了如何使用RxSwift。 剩下的唯一事情就是对应用程序进行单元测试。 RxSwift应用程序的单元测试与普通swift应用程序的单元测试非常相似。 再一次,最大的变化是我们与观察者一起处理所有的回调和数据更新。 在这篇文章中,我们将看到如何: 处理可观察对象并订阅事件。 模拟网络层以进行单元测试。 在单元测试中处理数据验证。 我们将测试的所有代码都在视图模型内部,因此您还将学习如何对视图模型进行单元测试。 如果您对单元测试的概念不太熟悉,建议您阅读我以前有关单元测试视图模型的文章。 您将获得单元测试的所有基本信息,并友好地提醒您为什么应该始终对应用程序进行单元测试! 😄 我们将通过对称为Friends的应用程序进行单元测试来学习这些知识。 Friends应用程序是我使用MVVM模式实现的应用程序。 使用“朋友”应用,您可以下载朋友列表,并使用UITableView将其显示给用户。 您还可以使用该应用创建,更新和删除朋友。 这是一个简单的应用程序,具有足够的功能,可以处理开发iPhone应用程序时遇到的许多基本问题。 我首先编写了不带RxSwift的Friends应用程序,然后想看看如果我使用RxSwift会更改多少代码。 如果您想进一步了解纯MVVM应用程序的实现,请查看我有关Swift应用程序的MVVM模式的文章。 如果您想了解我们今天测试的应用程序是如何实现的,请查看这篇文章:如何在MVVM中使用RxSwift。 所有代码都可以从GitHub下载。 只要记得签出RxSwift分支即可。 但是现在,让我们开始吧! 我们将从检查如何对FriendsTableViewViewModel进行单元测试FriendsTableViewViewModel 。 这是处理向用户显示朋友列表的类。 由于FriendsTableViewViewModel发出网络请求,因此我们要做的第一件事是模拟网络层以进行测试。 通常,我们不希望单元测试发出网络请求,因为: 从服务器获取答案可能需要一些时间,这会使测试运行缓慢。 由于网络或服务器,测试可能会失败,这使得无法可靠地验证结果。 通过模拟网络层,我们可以为当前测试用例返回合适的答案。 AppServerClient是处理应用程序中所有网络的类。 如果打开该类,我们将看到它具有一个名为getFriends的函数。 这是我们要在第一个测试中覆盖的功能。 它下载朋友列表,然后我们向用户显示该列表。 函数定义如下所示: 我们可以定义一个协议,该协议具有与AppServerClient相同的所有功能定义。 然后,我们可以使AppServerClient和模拟实现都符合该协议。 但是由于我们还没有可用的协议,因此我们将使用良好的旧继承。 MockAppServerClient继承自AppServerClient而我们已经覆盖了getFriendsFunction 。 我们在函数内部所做的第一件事是,我们创建了一个从函数返回的Observable 。 我们为create函数传递一个块,并将Switch用于名为getFriendsResult的变量。 getFriendsResult是用于定义网络请求的不同结果的变量。 成功的情况下,它包含一个朋友列表;失败的情况下,它包含一个错误。 稍后,我们将检查如何为测试定义值。 在switch语句中,我们定义了.success和.failure情况, .onNext订阅者发出带有朋友列表的.onError或带有错误值的.onError 。 我们已将getFriendsResult定义为Optional因为我们不想为模拟类定义初始化程序。 这就是为什么我们还需要在函数中定义.none大小写的原因。 最后,我们将Observable.create需要的虚拟一次性对象作为返回值返回。 RxSwift应用程序单元测试的第一步已经完成! […]

RxSwift#2 —可观察的과主题(+中继)알아보기

可观的下载, 可观察的主题 ,RxCocoa 中继的继电器 。 룬룬다룬룬알아 可观察的 Observable이지속적으로이있것을发射이라고다。 1.可观察的生命周期 next 통해1,2,3을可观察 뒤뒤종료된可观察 1,2에러에러종료된 error 를종료된可观察 이전다뤘던정정해보자 next :최신(다음)값을이벤트 error :可观察到的错误 complete :성공적으로이벤트스시퀀이벤트。 可观察的이더상배출하지않음

使用RxSwift切换组件

拨动开关列表在移动世界中广泛存在。 我在我使用的大多数应用程序的“设置”屏幕中找到它。 对我来说, 打开和关闭事物并将其保存在某个地方的简单动作隐藏了我将要揭示的有趣的复杂性。 在本文中,我将使用RxSwift构建“切换列表”屏幕。 我将使用上一篇有关自动完成的文章中介绍的技术。 我们将创建Toggle组件-一个带有输入和输出要插入的黑盒子。 阅读此书后,您将可以在项目中使用它来建立自己的切换体验。 切换 首先,了解我们将要积累的经验。 请注意,在将其状态发送到服务器时,单次切换处于禁用状态,有时它会摇动并退回到先前的状态-发生保存错误时: 在Swift中也一样: 并提供用于使用Toggle配置单个UISwitch支架: 现在,将在setUp(settingSwitch:with toggle:)完成输出编排。 它以settingSwitch和toggle作为参数。 在上面的视频中,对UISwitch进行了三种修改: settingSwitch.isOn属性使用切换初始值设置,以后可以使用切换后备值强制更改; settingSwitch.isEnabled已更改为Toggle活动; 播放settingsSwitch.shake()动画以切换回退值 。 第一个修改是由initialValue和fallbackValue流合并到单个switchValue流中定义的: switchValue流驱动rx.isOn属性。 虽然.flatMap { $0.map(Driver.just) ?? Driver.empty() } .flatMap { $0.map(Driver.just) ?? Driver.empty() }可能看起来很神秘,它只有在不为nil时才发出值。 如果使用RxSwiftExt库,则等于.unwrap() 。 为了提高代码的可读性,我们使用ToggleValue扩展的以下三个便捷属性: 第二个突变很简单: 否定isBusy输出以驱动器settingSwitch.rx.isEnabled 。 当fallbackValue出现在fallbackValue流上时,第三个突变播放.shake()动画: 我们不在乎fallbackValue发出的值,因此我们将其映射到void () 。 最后,通过UISwitch的此扩展来制作shake()动画: 值得注意的是, Toggle组件并不限制我们构建这种类型的UX。 某些应用会在服务器上保存设置时阻塞整个屏幕。 只需将多个isBusy输出合并到单个isLockViewVisible流中,即可使用Toggle轻松完成。 单元测试 因为唯一的Toggle’s依赖项是ToggleStorage ,它是一个协议,所以创建MockToggleStorage并完全测试Toggle非常容易。 一个很好的例子是该测试确保在用户输入后发出更新值。 我们使用帮助程序recordedValues数组存储value输出发出的所有值。 […]

通过RxSwift和ObjectMapper缓解Firebase的痛苦

本文是我在软件工程中的一些实用方法。 所有示例代码均使用Swift 3,Firebase 4.0,RxSwift 3.6.1和ObjectMapper 2.2.8编写 介绍 也许您知道,Firebase是跨平台开发工具的集合,包括实时数据库,分析,云消息传递,身份验证,Admob等。 但它最初是一个实时数据库,在2014年被Google收购之前。 背景 Firebase实时数据库(为了简短起见,从现在开始,我将说Firebase for Firebase实时数据库 )可能不适用于每个移动应用程序,但是在我们正在开发的iOS游戏项目中,它可以满足我们的需求,而且速度非常快。 这是一个普通Firebase对象的示例: 您可能希望它以平面以下的格式轻松地将它们映射到对象中。 我将为此提供一些解决方案。 { “ postId”:“ postId”, “ title”:“标题”, “ content”:“内容”, “ author”:“ userId” } 对象映射器 我经常使用ObjectMapper自动将JSON映射到Model对象。 有很多库,但是我很熟悉。 我将介绍JSON映射的两种基本情况 单对象映射 解决这个问题的第一种方法是每次查询Post对象时,将Firebase的DataSnapshot键手动添加到数据字典中 likes是一个包含userId列表的数组,但是我不想将其存储为[ String: Bool] 。 最好编写一个自定义转换。 邮政模型变为: 此外,您可以编写所需的任何自定义转换,例如在Int64时间戳和String日期格式之间进行转换。 RxSwift 什么是RxSwift? Rx代表ReactiveX,是“用于异步编程的API 带有可观察到的流”(http://reactivex.io)。 另外,有许多教程告诉您应该了解Rx的优点。 例如,Why-Rx,Why-Use-RxSwift。 RxSwift是Swift语言中Rx的实现,其中包括其他语言:Java,JS,C#,Python… 2.为什么选择Rx? Rx优雅地处理异步代码块。 它具有陡峭的学习曲线,但值得学习。 对我来说,带有RxSwift的Firebase非常强大。 3.行动中 首先,我用RxSwift封装了Firebase函数,该函数可以帮助您以一种更易读的反应方式查询Firebase。 […]

自动进行复杂的表格视图状态更改

这不是我的编程博客,但我无法抗拒发表此帖子。 我想为正在处理复杂(尤其是动态)表视图布局的iOS程序员提供帮助。 我也喜欢Kitchen Stories应用程序,很高兴看到他们在iOS开发中发表的帖子。 他们做登录屏幕的方式对我来说似乎很棒。 不过,还有改进的空间。 处理动态布局可能很困难。 这就是为什么发明了诸如响应式功能编程 (或FRP)之类的技术的原因。 如果您不知道什么是FRP,我建议您先看Ash Furrow的精彩演讲。 基本思想是,您以称为Observable 的值流的形式定义所有内容。 它可以包含任何内容:用户输入的文本,API的响应,通知。 您可以通过组合和绑定这些可观察对象来编写代码。 这些硬布局的一种情况是动态表视图。 关于它们的讨厌的事情是表具有状态 。 这意味着,如果要对表进行更改(并且希望这些更改看起来很整洁),则必须手动删除并插入行和节。 想象一下,您的表有很多状态。 您必须为状态之间的每个过渡指定插入和删除。 kes 厨房的故事做出了正确的决定,并使用了一个库来帮助他们自动计算两种状态之间的差异。 让我印象最深的一件事是,他们已经定义了声明式的状态,但仍然以命令式的方式对他们的观点进行操作。 但是,为什么不更进一步呢? 为什么我们必须编写所有这些deleteRowsAtIndexPath ? 我将使用RxSwift和RxDataSources的功能来实现一个解决方案。 第一个是Swift中FRP的实现,第二个是使用表视图和集合视图执行复杂操作的库。 给我看看代码! 好的,首先让我们在表格视图中显示一些东西 。 如果只想显示相同的数据会更容易,但是在这种情况下,我们必须对其进行动画处理,因此我们将不得不编写一些样板来定义我们的部分。 是时候弄脏我们的双手了! 是的,它有效! 我保证,我们仍然没有更改tableView,但是我们真的很接近。 我们现在要做的是1)定义状态 表视图中的2)提供了在它们之间切换的方法,3)将状态绑定到我们的表示形式。 做吧,这很容易! 首先是状态。 看起来确实如此! 但是等等,动画不是我们想要的。 让我们修复它。 看起来更好。 我们还希望显示正确的按钮标题,因此我们也要这样做以提高我们的反应能力。 是的,它有效! 恭喜,我们做到了。 在枚举中定义状态有一件很棒的事情:如果添加更多状态,则也将不得不更改变量定义,并且您不会错过任何事情。 您可以在这里做很多事情。 我们没有更改注册/登录按钮的标题,可能应该使用关联的值来完成,因此我们的枚举不再具有原始值。 我还将在实际应用程序中使用Drivers而不是Observables (它是用于开发UI的特殊Observable,您可以在此处阅读有关它们的信息)。 另外,您可以实施即时表单验证并相应地启用/禁用按钮。 使用FRP是一项非常容易的任务! 在这个简单的教程中,Rx似乎是一个过大的功能,但是我可以向您保证,我正在做非常复杂的表视图并进行了许多更改,直到使用RxDataSources时我才失败。 […]

使用RxSwift制作游乐场

注意:已在2017年3月10日更新为使用Xcode 8.2.1和CocoaPods 1.2.0。 情况 :您正在项目中使用RxSwift。 您意识到拥有一个操场来测试想法真的很好。 问题 :您无法将RxSwift(或RxCocoa)导入您的游乐场。 苹果公司的指示是不透明的。 解决方案 :使用CocoaPods安装RxSwift。 CocoaPods将创建一个包含RxSwift和您现有项目的工作区。 在项目内创建的工作区将能够导入RxSwift。 详细说明 :如果您尚未使用CocoaPods,请初始化一个新的Podfile : $ pod init 现在,您的项目目录中应该有一个Podfile 。 在您的Podfile添加以下段: #项目豆荚 pod’RxSwift’,’〜> 3.2′ 然后安装此pod: $ pod安装 现在您应该有一个工作区(扩展名为.xcworkspace )。 使用Xcode打开此文件。 现在,您可以创建您的游乐场了。 转到项目导航器,然后取消选择所有内容(⌘单击任何选定的项目)。 这很重要,因为在下一步中添加项目时,您希望它位于工作空间而不是现有项目下。 使用项目导航器中的“ +”按钮将新的Playground添加到工作区。 给您的游乐场起个名字。 我建议将其与Project.xcodeproj和Project.xcworkspace文件放在同一目录中。 保持在一起。 此时,您应该有一个工作区,其中项目,操场和吊舱都在工作区的顶层: 现在构建您的项目。 这还将建立您在上一步中选择的Rx目标。 您的构建应该成功! 现在转到您的游乐场并导入RxSwift。 使用RxSwift游乐场 您可能会注意到RxSwift在操场上的行为有所不同。 具体来说,如果您创建一个Observable.interval,它似乎没有任何作用。 那是因为您需要告诉Xcode继续连续运行您的Playground,否则它仅运行每个语句并立即停止执行,然后观察到的时间间隔可以发送事件。 可以通过在Playground / Sources下添加此SupportCode.swift文件来解决。 在操场的尽头,将调用添加到playgroundTimeLimit以指定您想让操场运行多长时间。 例如: PlaygroundTimeLimit(10) 这将使运动场保持运行10秒钟,此后运动场将自动停止,从而节省了笔记本电脑的电池并限制了输出缓冲区的大小。