在 iOS 开发过程中,我们几乎无时无刻都要面对异步事件的处理。例如,按键点击、数据保存、、音频后台播放、交互动画展示。这些事件并不具备特定时序性,甚至它们可能同时发生。

虽然 Apple 提供了通知、代理、GCD、闭包等异步机制,但是这些机制缺乏一个统一的抽象表述。另外,这些机制在处理共享的可变数据或状态时不够清晰简练。当然,这并不是说编写优雅的异步代码不现实。毕竟与其他平台相比 iOS 的异步机制还是很强大的。

幸运的是,我们能够通过 RxSwift 优雅的处理异步代码。

<!--more-->

至于 RxSwift 的优势以及为什么要使用它,详见文档。这里就不废话了。

RxSwift 简介

其实响应式编程并不是一个什么新的概念,只不过是最近几年受到了开发者更多的关注。它最早由巨硬提出,主要的目的是为了应对复杂的 UI 异步事件和应用实时响应。社区中也已经有了各种语言版本的响应式编程实现,包括:RxJS、RxKotlin、Rx.NET、RxScala、RxSwift。这些类库仅仅只是实现方式存在差异,所以开发者在讨论应用逻辑时不会存在沟通障碍。

RxSwift 作为 Swift 语言的响应式编程实现,它在传统的命令式编程和纯函数式编程中找到了一个很好的平衡点。通过使用不可变代码定义异步处理输入,RxSwift 以一种确定可组合的形式对事件做出响应。

总的来说,RxSwift 有三个主要构成部分:ObservableOperatorScheduler 。下面我们就来一一介绍。

Observable

Observable<T> 类可以说是 RxSwift 整个框架的基石。它能异步的触发一系列事件流并携带不可更改的状态变量。简单来说就是:它能让某个类的实例在一段时间内实现对另一个实例对象值的观察。例如:观察者可以捕获对所有可观察对象触发的事件,从而实现 UI 的实时更新或者是数据的实时处理。

其中 Observable<T> 类遵循了 ObservableType 协议。另外,Observable 对象所能触发的事件只有以下三种:

  1. next 事件:该事件在触发时会将可观察对象的最新值传递给观察者。
  2. completed 事件:该事件意味着可观察对象的生命周期正常结束不会在继续触发事件。
  3. error 事件:该事件表明可观察对象出现了错误导致生命周期异常终止。

对于一个可观察的整型变量来说,异步环境下它所触发的事件可以在时间线上被描绘成这样一个事件序列:

另外,我们可以对这三类事件进行组合从而实现更为复杂的业务逻辑。与此同时,我们还可以使用该机制轻松实现代码解耦和多个对象间数据传递,无需编写代理或者闭包代码。

这里,我们还有一点值得注意。那就是可观察序列其实有两种类型。

有限观察序列( Finite observable sequences )

该序列是指那些最后会以 completed 或者 error 事件终极生命周期的可观察对象。最典型的例子就是,通过 API 进行网络请求:

  1. 开始数据请求并准备进行数据接收。
  2. 接收到服务端响应开始接收数据。
  3. 如果服务器或者网络发生故障则关闭请求并触发错误处理。
  4. 如果一切正常则对请求数据进行处理和分析。

下面是一个文件下载请求的 Rx 范式的代码:

API.download(file: "http://www...")
    .subscribe( onNext: { data in
                        append data to temporary file },onError: { error in
                        display error to user },onCompleted: {
                        use downloaded file })

这段代码中 API.download (file:) 函数会创建一个 Observable<Data> 实例对象,并且在整个数据接收过程中会不断的触发 next 事件。然后,我们在 next 事件中会将这些片段数据保存到临时文件中。如果此过程出现错误的话,我们会将错误信息展示给用户。如果一切顺利我们会将临时文件保存到设备中。最后在下载完成后,我们可以在 completed 进行下一步的逻辑处理。

无限观察序列( Infinite observable sequences )

与网络任务不同的是,UI 以及交互事件是无限观察序列。它们并不存在一个明确的生命周期终结点。例如,针对可能的设备方向旋转,我们需要实时进行布局修改。而设备的方向旋转本身是随机发生的并且与应用本身具有同样的生命周期。因此 Rx 也需要一种机制支持这种无限观察序列。

针对这种情况,在 RxSwift 中我们可以通过以下代码来应对:

UIDevice.rx.orientation.subscribe(onNext: { current in 
    switch current { 
        case .landscape:
            re-arrange UI for landscape 
        case .portrait:
            re-arrange UI for portrait 
    } 
})

操作符

ObservableType 以及 Observable 类的实现中都包含大量的异步处理方法,这些方法也被称为操作符。由于这些操作符只是进行异步输入处理并产生对应输出,所以它并不会对应用产生多余的副作用。另外,因为操作符之间的高度解耦所以我们很容易对它进行组合以期实现复杂的功能。

例如,对于上面的设备方向旋转,我们可以对所有的情况进行过滤然后对部分值进行进一步处理。

UIDevice.rx.orientation
    .filter { value in
        return value != .landscape 
    } 
    .map { _ in
        return "Portrait is the best!" 
    } 
    .subscribe( onNext: { string in 
        showAlert(text: string) 
    })

上面的代码中,我们首先会将所有 .landscape 方向过滤掉不做任何处理。然后,我们再将剩下的 portrait 转化为字符串 Portrait is the best! 。整个处理流程大致如下:

这种函数式的操作符让我们可以灵活的组合出更强大的功能。

Scheduler

Schedulers 是一个与 GCD 相对应的概念,只不过前者使用起来更为方便。RxSwift 中预定义的 Schedulers 足够开发者应对绝大多数的编程场景。

例如,我们可以使用串型序列 SerialdispatchQueueScheduler 来处理 next 事件,通过 ConcurrentdispatchQueueScheduler 运行并行文件下载任务,通过 OperationQueueScheduler 运行一个 NSOperationQueue 操作队列。甚至你可以在同一个观察对象的不同任务中使用不同的 Schedulers 类型,如下图:

我们将左侧的任务用不同的颜色加以区分,然后在右侧任务被拆分为不同的步骤并且放在不同 Schedulers 中。例如,network subscription 任务就被拆分为三个步骤并依次放入了 Custom NSOperation SchedulerBackground Concurrent SchedulerMain Thred Serial Scheduler

补充

值得注意的是, RxSwift 并没有对客户端的应用架构作出硬性规定。这意味着,我们可以在已有项目中引入 RxSwift 进行响应式编程实践。当然已有框架中必定存在一个最适合 RxSwift 的,而它就是 MVVM。因为在 MVVM 中我们可以将 VM 中的部分属性直接与 UI 进行绑定。

另外,对于 iOS 编程来说仅仅有 RxSwift 是远远不够的。RxSwift 只是 Swift 语言的响应式实现,我们还需要一种 Cocoa 层面的实现。好在这里存在 RxCocoa 作为 UIKit 的响应式补充。前面设备方向代码 UIDevice.rx.orientation 就是 RxCocoa 的应用 。

总结

作为系列开篇,本文介绍了 RxSwift 的一些基本理念和构成,更多相关的内容将会在后面带来。

原文地址

RxSwift 基础的更多相关文章

  1. ios – RxSwift:返回一个带有错误的新observable

    我有一个函数返回BoolObservable,具体取决于它是否正常.解决方法返回包含单个元素的可观察序列.相反,你应该使用这样的东西:Create方法从指定的subscribe方法实现创建一个可观察的序列.在你的情况下:Anonymousdisposable是在您想要中断的情况下调用的操作.假设您离开视图控制器或应用程序需要完成该服务,您不再需要再调用此请求.它非常适合视频上传或更大的内容.您可以

  2. ios – RxSwift:使用rx_refreshing进行uirefreshcontrol

    我正在使用UIRefreshControl变量绑定来重新加载数据.然而,它正在起作用,以下对我来说是错误的:1)我知道RXCocoa扩展中有一个rx_refreshing变量,但我无法让它在这个上下文中工作.2)我绑定答案两次.一旦我加载视图控制器,当UIRefreshControl刷新时再次加载.3)我检查UIRefreshControl是否令人耳目一新的部分看起来很尴尬.感觉它是否违背了使用反应的目的?

  3. ios – 将UIApplicationDelegate方法转换为RxSwift Observables

    得到打印然后我在RxCocoa的_RXDelegateProxy_类中得到以下崩溃:有谁知道问题可能是什么?或者有没有人成功实现过像rx_applicationDidBecomeActive这样的东西?

  4. 在实践中应用 RxSwift

    注:本文基于Swift3。Swift大会上有一场POP的分享,Demo地址RxPagination。摘要在上一篇在实践中应用RxSwift1-使用Result传递值中,我们解决了error的处理,但当我们处理一段很长的事件流时,会发现有很多不重要的代码,比如传递Error。在Rx中,map和flatMap是最常用的,我们添加一些小工具。以此表示这个方法是用在flatMap上的。关于为什么FlatMap中会有filter,您可以参考这篇文章用更Swifty的代码遍历数据。

  5. RxSwift使用教程

    前言RxSwift是Swift函数响应式编程的一个开源库,由Github的ReactiveX组织开发,维护。RxSwift的目的是让让数据/事件流和异步任务能够更方便的序列化处理,能够使用Swift进行响应式编程目前,RxSwift在Github上收到了5000+Star,600+fork。RxSwift的核心思想和这个类似。RxSwift的核心是想是Observablesequence,Observable表示可监听或者可观察,也就是说RxSwift的核心思想是可监听的序列。

  6. 初识RxSwift及使用教程 韩俊强的博客

    RxSwift是Swift函数响应式编程的一个开源库,由Github的ReactiveX组织开发、维护其他语言像C#,Java和JS也有,Rx.Net、RxJava、RxJSRxSwift的目的是让让数据/事件流和异步任务能够更方便的序列化处理,能够使用Swift进行响应式编程函数式响应编程?

  7. RxSwift使用教程大全 韩俊强的博客

    记录大多数ReactiveX的概念和操作符。我们还需要使用KVO来检测变量的值改变。Rx就是为解决这些问题而生的。Observable理解RxSwift的关键是理解Observable的概念。使用variable的好处是variable将不会显式的发送Error或者Completed。

  8. RxSwift 基础

    幸运的是,我们能够通过RxSwift优雅的处理异步代码。通过使用不可变代码定义异步处理输入,RxSwift以一种确定可组合的形式对事件做出响应。ObservableObservable类可以说是RxSwift整个框架的基石。补充值得注意的是,RxSwift并没有对客户端的应用架构作出硬性规定。这意味着,我们可以在已有项目中引入RxSwift进行响应式编程实践。当然已有框架中必定存在一个最适合RxSwift的,而它就是MVVM。总结作为系列开篇,本文介绍了RxSwift的一些基本理念和构成,更多相关的内容将

  9. RxSwift 之 Observable

    --more-->在前一篇基础之上,本文我们将会介绍RxSwift中的Observables部分。在RxSwift中Observable也被称为ObservableSequence、Sequence、Stream。Observable会以异步的方式不断的发射事件形成事件流,并且数据也会沿着事件流进行传播。Observable生命周期上图中的三个圆圈其实就是RxSwift中的next事件。订阅Observable在日常iOS编程中,通知模式可以说是使用频率相当高的一个设计模式。更为重要的是,在没有订阅者的时

  10. RxSwift 之变换操作

    可能刚开始接触RxSwift时候,你会觉得RxSwift非常难懂也不容易学。不过我相信认知读了前几篇文章后,你会深感RxSwift的强大。这篇文章将会继续介绍另一组非常重要的RxSwift操作:TransformingOperator。RxSwift中实现此功能最简单的方法就是通过toArray操作。而flatMap在RxSwift中的操作过程如下图:图中第一行O1、O2、O3表示三个类型实例,然后该类型实例有一个可观察属性value。总结本文简单了介绍了RxSwift中一些常见的变换操作。

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部