首页 >iOS开发

RxSwift之路 1#Swift语法知识准备

2017-07-12 15:05 编辑: sasukeo 分类:iOS开发 来源:没故事的卓同学的简书

原文

在开始学习 RxSwift 之前,一定要对 Swift 相关语法有所了解,否则就很难理解为什么可以这样。关于 Swift 的学习其实只要看看 Swift 的官方文档就可够了。我之前也列过一些学习资源:来自一线开发者的Swift学习资源推荐

现在开始进入正题。

Swift的优势

想一个有趣的问题,为什么没有 RxObjc 呢?

实际上响应式的编程框架对语言还是有些要求的,当然 OC 确实也有一个奠基式的 FRP 框架 ReactiveCocoa。但是客观的说,在 Swift 里响应式的框架写起来会愉快的多,或者说更能发挥出语言的优势。

Swift 契合响应式有以下几点:

  • 强类型,强类型的泛型

  • 灵活的闭包

  • 对并发模型的原生支持(Swift 5 的特性,还未发布)

Enum的关联值和泛型

Swift 中的枚举(Enum)能力相比 OC 可以说得到了升华。不再只是一个类似预编译时的宏,而是一个完整的类型。和 Struct 一样,可以给他定义初始化方法,声明函数,添加扩展。同样的泛型同样也试用于 Enum。

枚举还有一项神奇的能力叫关联值。一个枚举可以的值可以是不同的类型。官方手册里的示例代码如下:

enum ServerResponse {
    case result(String, String)
    case failure(String)
}

let success = ServerResponse.result("6:00 am", "8:09 pm")
let failure = ServerResponse.failure("Out of cheese.")

switch success {
case let .result(sunrise, sunset):
    print("Sunrise is at \(sunrise) and sunset is at \(sunset).")
case let .failure(message):
    print("Failure...  \(message)")
}

每个 case 可以携带不同的类型,并且可以不止是一个值。

当 Enum 结合泛型,就发生了有趣的事。直接贴代码:

enum OptionalValue {
    case none
    case some(Wrapped)
}

var possibleInteger: OptionalValue = .none
possibleInteger = .some(100)

这就是 Swift 中的 Optional 实现的类似代码。使用枚举实现,表示值有两种可能:没有值的 .none 和是 Wrapped 类型的 .some。

有了以上的知识我们再来看 Rx 中的事件流中的值Event:

public enum Event {
    /// Next element is produced.
    case next(Element)

    /// Sequence terminated with an error.
    case error(Swift.Error)

    /// Sequence completed successfully.
    case completed
}

每一次事件的值有三种可能:1.值(next),2.完成结束(completed),3.失败(error)。

函数的默认参数

如果函数在声明时设置了一个默认值,那么在调用时这个参数就可以不传。

假设我们给 Int 定义个扩展方法increment。如果不传入值则默认加1,如果传入就按照传入的值增加:

extension Int {
    func increment(with number: Int = 1) -> Int {
        return self + number
    }
}

使用的时候 Xcode 就会提示两个函数:

225849-00c73b55812bf7fa.png

不再需要像 OC 一样定义几个函数。

Rx 表示订阅的subscribe函数,有时只要写onNext,有时只要写onError,就是因为这个函数在声明时同时指定了默认参数:

extension ObservableType {

   public func subscribe(file: String = #file,line: UInt = #line,
                                          function: String = #function,
                                          onNext: ((E) -> Void)? = nil,
                                          onError: ((Swift.Error) -> Void)? = nil, 
                                          onCompleted: (() -> Void)? = nil,
                                          onDisposed: (() -> Void)? = nil)-> Disposable {
     // ...
    }

可以看到这个函数为订阅每个事件可能都声明了默认参数,所以你在订阅时可以只订阅自己关注的订阅。

闭包

闭包的使用类似 OC 中的 block,具体使用就不再介绍。提一下新手很容易忽略的语法糖。

闭包简化语法

  • 闭包参数、返回值类型自动推断

    因为 Swift 是强类型语言,闭包的参数的类型可以推断出来。比如如下代码:

reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
  return s1 > s2
})
  • s1 和 s2 的类型和返回值类型 Xcode 可以推断出来可以省略:

reversedNames = names.sorted(by: { (s1, s2)  in
  return s1 > s2
})
  • 闭包表达式只有一行,可以省略return

    因为只有一行,表达式执行的结果肯定就是要返回的值,所以可以省略。接上面的代码可以优化成这样:

reversedNames = names.sorted(by: { 
         (s1, s2)  in   s1 > s2
})
  • 用$N代替参数

    有时实参的参数名没什么用,可以直接用$N代表实参,$0代表第一个参数。上面的代码进行这样的简化后就写成了这样:

reversedNames = names.sorted(by:  { $0 > $1 })
  • 二元运算时可以直接省略只用操作符表示

当表达式只有一行时,二元运算的表达式可以直接省略到只剩一个运算符,上面的可以省略为:

reversedNames = names.sorted(by:  >)

尾闭包

当参数的最好一个参数是闭包时,可以直接把最后一个闭包的实现跟在函数后面。

直接贴代码表示:

// 一个最后一个参数是闭包的函数
func someFunctionThatTakesAClosure(closure: () -> Void) {
    // function body goes here
}

// 默认的调用方法
someFunctionThatTakesAClosure(closure: {
    // closure's body goes here
})

// 省略最后一个参数的方法名,并且把闭包的实现直接跟在函数后面
someFunctionThatTakesAClosure() {
    // trailing closure's body goes here
}

这种写法简化了代码,让代码看起来更简洁。

Rx 中的数据流操作符可以灵活的组织闭包,经常会用到简化的闭包的语法。

  Observable.of(1, 2, 3, 4, 5, 6)
    .filter { $0 % 2 == 0}
    .subscribe(onNext: {
      print($0)
})

刚开始的时候可能有点看不明白,慢慢的还原闭包的语法,之后看多了就会熟悉的。

欢迎关注我的微博:@没故事的卓同学

链接:http://www.jianshu.com/p/5ad37c6d921e

來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

225849-a73f97c52f767ee7.jpg

搜索CocoaChina微信公众号:CocoaChina
微信扫一扫
订阅每日移动开发及APP推广热点资讯
公众号:
CocoaChina
我要投稿   收藏文章
上一篇:学习WebGL之透视和正交投影
下一篇:ARKit 从零到一:教你编写 AR 立方体

相关资讯

我来说两句
发表评论
您还没有登录!请登录注册
所有评论(0

综合评论

相关帖子

sina weixin mail 回到顶部