Skip to content

Commit 0648c29

Browse files
committed
Add Content and Images
1 parent 1114f62 commit 0648c29

File tree

2 files changed

+109
-2
lines changed

2 files changed

+109
-2
lines changed

chapter5/networking_layer_revisited.md

Lines changed: 109 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,112 @@ Completion blocks?这是另外一个使用Signals的机会。更深入一点来
5555
```
5656
这里有两个大的不同:
5757

58-
1. asdf
59-
2. asdf
58+
1. 我们使用RAC来绑定`downloadFullsizedImageForPhotoModel:`返回的信号的最新值。
59+
2. 我们返回`NSURLConnection的rac_sendAsynchronousRequest:`返回值的映射。
60+
61+
我们来看看这里究竟发生了什么。
62+
看文档:`rac_sendAsynchronousRequest:`返回一个发送网络请求响应值的信号。`RACTuple`它所发送的内容分别包含响应和数据。有网络错误发生时,它会抛出错误。 最后我们改变线程的调度,将signal切换到主线程上。 (一个线程的调度者类似于一个线程。)
63+
64+
看,网络信号将会把它的值返回给后台的调度者,如果我们不阻止它,它可能最终会去从事更新UI的事件,而后台线程是没有能力更新UI的。
65+
66+
我们回过头来看看最开始的那两行。注意下这行:
67+
68+
```Objective-C
69+
RAC(photoModel, thumbnailData) = [self download:photoModel.thumbnailURL];
70+
```
71+
72+
通常,我不推荐将一个model绑定到多个signal,然而,我们知道这个信号会在完成网络调用后立即执行完并结束订阅。只要我们仅在一个实例上绑定这个keyPath,这种就是安全的。
73+
74+
我们可以用类似的方式抽象掉使用`RACReplaySubject`的部分,来重新审视我们的`fetchPhotoDetails:`方法吧。
75+
76+
```
77+
+ (RACReplaySubject *)fetchPhotoDetails:(FRPPhotoModel *)photoModel {
78+
RACReplaySubject *subject = [RACReplaySubject subject];
79+
80+
NSURLRequest *request = [self photoURLRequest:photoModel];
81+
[NSURLConnection sendAsynchronousRequest:request
82+
queue:[NSOperationQueue mainQueue]
83+
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
84+
if(data) {
85+
id results = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil][@"photo"];
86+
[self configurePhotoModel:photoModel withDictionay:results];
87+
[self downloadFullsizedImageForPhotoModel:photoModel];
88+
[subject sendNext:photoModel];
89+
[subject sendCompleted];
90+
}
91+
else {
92+
[subject sendError:connectionError];
93+
}
94+
}];
95+
96+
97+
return subject;
98+
99+
}
100+
```
101+
102+
有一点点凌乱,我们来整理下。
103+
104+
105+
```Objective-C
106+
+ (RACSignal *)fetchPhotoDetails:(FRPPhotoModel *)photoModel {
107+
NSURLRequest *request = [self photoURLRequest:photoModel];
108+
return [[[[[[NSURLConnection rac_sendAsynchronousRequest:request]
109+
map:^id(RACTuple *value){
110+
return [value second];
111+
}]
112+
deliverOn:[RACScheduler mainThreadScheduler]]
113+
map:^id (NSData *data) {
114+
id results = [NSJSONSerialization JSONObjectWithData:data
115+
options:0 error:nil][@"photo"];
116+
[self configurePhotoModel:photoModel withDictionary:results];
117+
[self downloadFullsizedImageForPhotoModel:photoModel];
118+
return photoModel;
119+
}] publish] autoconnect];
120+
}
121+
```
122+
123+
**注意:** 返回值从`RACReplaySubject *`变成了`RACSignal *`.
124+
这里有很多地方需要梳理,所以我们提前做了下面这个示意图来说明:
125+
126+
![RACSignal_Process_Diagram](../images/racsignal_process_diagram.png)
127+
128+
我们已经知道`deliverOn:`是怎样工作的,所以让我们来关注信号链条最末端的信号操作`publish`. `publish`返回一个`RACMulitcastConnection`,当信号连接上时,他将订阅该接收信号。`autoconnect`为我们做的是:当它返回的信号被订阅,连接到
129+
该(订阅背后的)信号(underly signal)。
130+
131+
执行获取每一个订阅,在订阅的时候,我们返回的信号将会变“冷”。那是因为我们对底层信号进行多播,网络请求只会执行一次,但是它的结果被多播。这会导致:网络信号将只会被执行一次(当它被订阅时执行),是冷的(直到订阅为止,它不会被执行),甚至可删除的(如果一次性处理订阅的生成)。
132+
133+
基本上,我们能保证信号只会被订阅一次,我们不需要回滚(replay).
134+
135+
注意:我们可以用下面的`reduceEach:`替代使用`RACTuple`的第一个`map:`,以便提供编译时检查。
136+
137+
```
138+
reduceEach:^id(NSURLResponse *response, NSData *data) {
139+
return data;
140+
}]
141+
```
142+
143+
剩下的网络访问接口,`importPhotos`方法重构如下:
144+
145+
```
146+
+ (RACSignal *)importPhotos {
147+
NSURLRequest *request = [self popularURLRequest];
148+
149+
return [[[[[[NSURLConnection rac_sendAsynchronousRequest:request]
150+
reduceEach:^id(NSURLResponse *response , NSData *data){
151+
return data;
152+
}]
153+
deliverOn:[RACScheduler mainThreadScheduler]]
154+
map:^id (NSData *data) {
155+
id results = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
156+
return [[[results[@"photo"] rac_sequence]
157+
map:^id (NSDictionary *photoDictionary) {
158+
FRPPhotoModel *model = [FRPPhotoModel new];
159+
[self configurePhotoModel:model withDictionary:photoDictionary];
160+
[self downloadThumbnailForPhotoModel:model];
161+
return model;
162+
}] array];
163+
}] publish] autoconnect];
164+
}
165+
```
166+
95.4 KB
Loading

0 commit comments

Comments
 (0)