Home Learning ReactiveSwift - Part 2
Post
Cancel

Learning ReactiveSwift - Part 2

数据流

FRP之前一篇已经介绍过,是一种抽象的数据流型的编程思想。对于数据流,开始一个数据流后,会产生很多事件。在ReactiveSwift中,定义的事件有Event、Error。对应Observer则会有observe value、failed、complete、interrupted。

对于冷信号:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
let observer = Signal<Int, NSError>.Observer(
    value: { print("value: \($0)") },
    failed: { print("failed with \($0)")},
    completed: { print("complete") },
    interrupted: { print("interupted") }
)

SignalProducer<Int, NSError>([1,2,3,4]).start(observer)
/*
print:
value: 1
value: 2
value: 3
value: 4
complete
 */

 // or

let producer = SignalProducer<Int, NSError>([1, 2, 3, 4])

producer.startWithSignal { (signal, disposable) in
    signal.observe({ (event) in
        switch event {
        case .value(let value):
            print("value: \(value)")
        case .failed(let error):
            print("failed with \(error)")
        case .interrupted:
            print("interrupted")
        case .completed:
            print("completed")
        }
    })
}

对于热信号:

1
2
3
4
5
6
7
8
9
10
11
12
13
let (signal, observer) = Signal<String, TestError>.pipe()
signal.observe { event in 
	 switch event {
        case .value(let value):
            print("value: \(value)")
        case .failed(let error):
            print("failed with \(error)")
        case .interrupted:
            print("interrupted")
        case .completed:
            print("completed")
    }
}

需要注意的是,在signal接收到failed, interrupted, complete事件后,该通道就相当于关闭了,之后的事件则不会再接收到。

Map

map就像一般函数式编程中map用法一样,对sequence内对象进行transform,如下面例子,对数组中的数进行乘2:

1
2
3
4
5
SignalProducer<Int, NoError>([1, 2, 3, 4])
    .map { $0 * 2 }
    .startWithValues { print($0) }
// print: 
// 2 4 6 8

mapError是对failed情况进行transform:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
enum TestError: Error {
    case code(Int)
}

SignalProducer<Int, NSError>(error: NSError(domain: "test.domain", code: 100, userInfo: nil))
    .mapError { return TestError.code($0.code) }
    .startWithFailed { (error) in
    switch error {
    case let .code(code):
        print(code)
    }
}

// print: 100

flatMap是对SignalProducer进行转换

1
2
3
4
5
6
7
8
9
10
11
12
SignalProducer<Int, NoError>([ 1, 2, 3, 4 ])
    .flatMap(.latest) { SignalProducer(value: $0 + 3) }
    .startWithValues { value in
        print(value)
}
/*
print:
4
5
6
7
*/

Filter

对Value进行过滤,只有符合条件的value才能触发事件:

1
2
3
4
5
6
SignalProducer<Int, NoError>([ 1, 2, 3, 4 ])
	.filter { $0 > 3 }
	.startWithValues { value in
		print(value)
	}
// print: 4

Take

取事件的前N项(take(first:))或后N项(take(last:))

1
2
3
4
5
6
let producer = SignalProducer<Int, NSError>([1, 2, 3, 4])
producer
    .take(last: 2)
    .startWithResult { print($0) }
// .success(3)
// .success(4)

Combine

combineLatest是把第一个producer的最后一项与第二个producer的value进行绑定:

1
2
3
4
5
6
7
8
9
10
11
let producer1 = SignalProducer<Int, NoError>([ 1, 2, 3, 4 ])
let producer2 = SignalProducer<Int, NoError>([ 1, 2 ])

producer1
    .combineLatest(with: producer2)
    .startWithValues { value in
        print("\(value)")
}
// print:
// (4, 1)
// (4, 2)

combinePrevious是每次value都绑定前一次event的value

1
2
3
4
5
6
7
8
9
10
11
12
SignalProducer<Int, NoError>([ 1, 2, 3, 4 ])
    .combinePrevious(42)
    .startWithValues { value in
        print("\(value)")
}
/* 
print :
(42, 1)
(1, 2)
(2, 3)
(3, 4)
*/

小结

对于SignalProducer和Signal,还有很多方便的小工具对其进行操作或者转换,在实际使用过程中根据需求的不同进行使用。

This post is licensed under CC BY 4.0 by the author.

Learning ReactiveSwift - Part 1

RxSwift 在工程中的应用