Skip to content

Commit 75122d0

Browse files
committed
add Illustrations
1 parent bc43dc8 commit 75122d0

23 files changed

+36
-22
lines changed

chapter4/deriving_state.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
假设我们的视图是用来创建账户的,我们只允许包含有'@'字符的Email地址,当且仅当,输入的用户名有效时使按键可用,同时我们也希望通过TextField中Text的颜色给用户提供反馈。
55

66
- 首先我们使用IBOutlet在视图上增加一个按键‘button’.
7+
![added_a_button](../images/added_a_button.png)
78
- 其次我们将button的enable属性与我们创建的信号绑定。
89

9-
```
10+
```Objective-C
1011
RAC(self.button, enabled) = [self.textField.rac_textSignal map:^id (NSString *value){
1112
return @([value rangeOfString:@"@"].location != NSNotfound);
1213
}];
@@ -16,7 +17,8 @@ RAC(self.button, enabled) = [self.textField.rac_textSignal map:^id (NSString *va
1617
`RAC()`宏需要两个参数:‘对象’以及这个对象的某个属性的'keyPath'。然后将表达式右边的值和'keyPath'做一个单向的绑定,这个值必须是NSObject类型,所以我们会把boolean量封装成NSNumber。
1718
1819
但是,文本的颜色怎么办?实际上我们在这个基础上做一点点重构就可以了。
19-
```
20+
21+
```Objective-C
2022
RACSignal * validEmailSignal = [self.textField.rac_textSignal map:^id (NSString *value){
2123
return @([value rangeOfString:@"@"].location != NSNotFound);
2224
}];
@@ -33,5 +35,9 @@ RAC(self.button, textColor) = [validEmailSignal map: ^id (id value){
3335
3436
```
3537

38+
![invalid_email_address](../images/invalid_email_address.png)
39+
40+
![valid_email_address](../images/valid_email_address.png)
41+
3642
很好!看到我们怎样复用validEmailSignal吗?这在ReactiveCocoa中是非常常见的用法。在viewDidLoad方法之外,我们也不用写任何代码,这也很常见。
3743

chapter4/multicasting.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33

44
所以与其从这样的信号中创建一个`RACMulticastConnection`,不如使用`RACSignal``publish`方法或者`multicast:`方法。前者为您创建一个组播连接,后者也一样为您创建一个组播连接但需要一个`RACSubject`参数。当她被调用时这个RACSubject可以通过底层信号发送一个值出来。任何对这个值有兴趣的,都可以用这个从底层信号发送一个值到连接的信号来替代你提供的`RACSubject`,这个信号恰好就等同于你的这个`RACSubject`.
55

6+
为了说明这种不同,请参考下面的插图:
7+
8+
![multiple_subscriptions](../images/multiple_subscriptions.png)
9+
610
由于信号是冷启动的,每增加一个订阅者,她就会被执行一次。这种情况是我们不希望看到的,可以使用组播连接来改善。
711

12+
![multicast_connection](../images/multicast_connection.png)
13+
814
信号的组播连接订阅,当她传送一个新值的时候,是通过公共频道来传送给信号的。只要你喜欢你可以随意订阅这个信号,但这个信号在订阅相关的操作上有且仅会执行一次,不再像以前那样增加一个订阅者这个信号上就执行一次订阅相关的操作。

chapter4/signals.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,7 @@
1717

1818
信号是ReactiveCocoa的核心组件之一。ReactiveCocoa为UIKit的每一个控件内置了一套信号选择器。例如,UITextField就有一个`rac_textSignal`,UITextField中每一次按键的响应都会通过它发送出去。下一章我们会学习如何使用信号来执行任务。
1919

20+
![ClassDiagram](../images/Class_diagram.png)
21+
2022
信号也可以被链接(链式调用)和转化。通过映射或者过滤一个流得到的新的流也可以随后被映射、被过滤,进行所有你能想到的各种操作。下一章我们将了解更多这方面的内容。
2123

chapter4/subscriptions.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# 订阅
22
当你随时都想知道某一个值的改变时(不管是next、error或者completion),你就会订阅流---一种最常见的signal.使用信号通常都会有副作用,比如下面这个例子。
33

4-
  我们添加一个textfield控件到viewController's View上,这里我使用storyboard来做,你怎么做随你喜好咯。
4+
  我们添加一个textfield控件到viewController's View上,这里我使用storyboard来做,你怎么做随你喜好。
5+
6+
![adding_a_text_field](../images/adding_a_text_field.png)
57

68
在ViewDidLoad中添加如下代码,订阅textfield的rac_textSignal。
79

@@ -15,7 +17,11 @@
1517
}];
1618
```
1719

18-
创建并运行应用程序,在textField上输入一些内容。每一次每一个新的值输入到textField中,这个`Next value`就会下发到管道中,然后我们的订阅块就会被执行。有趣的是,这个特殊的信号不会发送错误值,仅仅在释放的时候发送一个完成值,所以这两个订阅块通常不会被调用。我们可以使用RACSignal上的一个简便的方法`subsribeNext:`来简化我们的代码:
20+
创建并运行应用程序,在textField上输入一些内容。每一次每一个新的值输入到textField中,这个`Next value`就会下发到管道中,然后我们的订阅块就会被执行。
21+
22+
![inputSomethingToTextField](../images/input_something_to_textfield.png)
23+
24+
有趣的是,这个特殊的信号不会发送错误值,仅仅在释放的时候发送一个完成值,所以这两个订阅块通常不会被调用。我们可以使用RACSignal上的一个简便的方法`subsribeNext:`来简化我们的代码:
1925
```
2026
[self.textField.rac_textSignal subscribeNext:^(id x){
2127
NSLog(@"New Value: %@", x);

chapter5/adding_to_functionalReactivePixels.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,4 +310,6 @@
310310

311311
好了。我们现在可以运行这个应用,点击一个图片去查看它的高清图片。我们也可以向前或者向后滑动来查看前一个或后一个高清图片。非常棒!
312312

313+
![fullsize_gallerypictures](../images/fullsize_gallerypictures.png)
314+
313315

chapter5/basic_of_functionalReactivePixels.md

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
# FunctionalReactivePixels的基础知识
22
FunctionReactivePixels将会是一个简单的观看'500px'中最受欢迎的照片的应用。一旦我们完成这一节,应用的主界面将会像下面这样:
33

4-
> 插入一个图片
4+
![app_main_page](../images/app_main_page.png)
55

66
当然我们也可以像下图一样观看全屏模式下的图片。
77

8-
> 插入一个图片
8+
![app_secondary_detailpage](../images/app_secondary_detailpage.png)
99

1010
这个App将使用Collection Views。如果你没有太多这方面的经验,也不需要太过担心---他们(CollectionView)就像TableView一样,使用起来非常简单。如果你对UICollectionView感兴趣,可以阅读我的[另一本书](http://www.amazon.com/iOS-UICollectionView-Complete-Edition-Programming-ebook/dp/B00IHZKDCU).
1111

1212
我们将使用CocoaPods来管理我们的依赖,现在创建一个新的工程。我喜欢使用空模版以便我可以完全控制viewController层级。
1313

14+
![app_project_create](../images/app_project_create.png)
15+
1416
首先、我们将创建一个UICollectionViewController的子类FRPGalleryViewController.同时我们创建一个UICollectionViewFlowLayout的子类FRPGalleryFlowLayout.
1517

1618
```
@@ -58,6 +60,8 @@ FunctionReactivePixels将会是一个简单的观看'500px'中最受欢迎的照
5860
```
5961
很好!如果我们现在运行,我们将看到一个空视图。
6062

63+
![app_main_emptypage](../images/app_main_emptypage.png)
64+
6165
我们来填充一些内容。创建一个Podfile文件,并填写如下内容:
6266
```
6367
platform :ios, "7.0"
@@ -238,19 +242,7 @@ else{
238242

239243
这个`map`(映射)非常有意思。序列中的每一个元素,都会创建一个新的`FRPPhotoModel`对象、设置它然后返回它。为每一个`results[ @"photos" ]`的数组元素创建了一个`FRPPhotoModel`数组。这个数组就是随着subject发送过来的值。最后我们发送一个完成值`completedValue`好让订阅者们知道任务完成了。
240244

241-
|原始值| 映射 | 映射值 |
242-
| :---: | :---: | :---:|
243-
| {values} | map | FRPPhotoModel |
244-
| {values} | map | FRPPhotoModel |
245-
| {values} | map | FRPPhotoModel |
246-
| {values} | map | FRPPhotoModel |
247-
| {values} | map | FRPPhotoModel |
248-
| {values} | map | FRPPhotoModel |
249-
| {values} | map | FRPPhotoModel |
250-
| {values} | map | FRPPhotoModel |
251-
| {values} | map | FRPPhotoModel |
252-
| {values} | map | FRPPhotoModel |
253-
245+
![value_photoModel_map](../images/value_photoModel_map.png)
254246

255247
注意在信号上手动附送值的能力是非典型的,这是RACSubject实例的专属能力。
256248

@@ -300,7 +292,7 @@ else{
300292
- 然后,将这些符合要求的字典做一次映射来提取字典中`url`字段的内容。
301293
- 最后,我们获得一个NSString 对象的序列,把它转化为数组,然后返回`firstObject`.
302294

303-
> 这里插图一个
295+
![error_handling](../images/error_handling.png)
304296

305297
在ReactiveCocoa中类似上面的链式调用非常常见。值从`rac_sequence`推送到`filter:`方法中,最后推送到`map:`方法里。最后调用序列`rac_sequence``array`方法,将序列的结果转化为`array`.
306298

@@ -475,7 +467,7 @@ static NSString * CellIdentifier = @"Cell";
475467
}];
476468
```
477469

478-
> 插入一个插图
470+
![chained_signal](../images/chained_signal.png)
479471

480472
信号由`RACObserver`这个C的宏生成,这个宏简单地返回一个监控目标对象关键路径值变化的信号。在我们这个例子中,我们的目标对象是`photoModel`,关键路径为`thumbnailData`属性。我们过滤掉所有的nil值,然后对过滤后的值做映射:把NSData实例转为UIImage对象。
481473

@@ -498,7 +490,7 @@ thumbnailData属性根本不需要在这里设置,他可以在稍后的某个
498490

499491
这个方法在Cell被复用之前调用。如果现在运行我的应用,我们可以看到下面的结果:
500492

501-
> 插图
493+
![disposing_subscription_works](../images/disposing_subscription_works.png)
502494

503495
太好了!我们可以通过滚动视图来证实我们手动处理订阅的有效性。
504496

images/Class_diagram.png

20.4 KB
Loading

images/added_a_button.png

428 KB
Loading

images/adding_a_text_field.png

514 KB
Loading

images/app_main_emptypage.png

102 KB
Loading

0 commit comments

Comments
 (0)