-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
1147 lines (560 loc) · 69.5 KB
/
index.html
File metadata and controls
1147 lines (560 loc) · 69.5 KB
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!doctype html>
<html class="theme-next pisces use-motion">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<link href="/vendors/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />
<link href="//fonts.useso.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
<link href="/vendors/font-awesome/css/font-awesome.min.css?v=4.4.0" rel="stylesheet" type="text/css" />
<link href="/css/main.css?v=5.0.1" rel="stylesheet" type="text/css" />
<meta name="keywords" content="Hexo, NexT" />
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.0.1" />
<meta name="description">
<meta property="og:type" content="website">
<meta property="og:title" content="Hexo">
<meta property="og:url" content="http://yoursite.com/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:description">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Hexo">
<meta name="twitter:description">
<script type="text/javascript" id="hexo.configuration">
var NexT = window.NexT || {};
var CONFIG = {
scheme: 'Pisces',
sidebar: {"position":"left","display":"post"},
fancybox: true,
motion: true,
duoshuo: {
userId: 6300064656572548000,
author: '博主'
}
};
</script>
<title> Hexo </title>
</head>
<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">
<div class="container one-collumn sidebar-position-left
page-home
">
<div class="headband"></div>
<header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-meta ">
<div class="custom-logo-site-title">
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<span class="site-title">Hexo</span>
<span class="logo-line-after"><i></i></span>
</a>
</div>
<p class="site-subtitle"></p>
</div>
<div class="site-nav-toggle">
<button>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
</button>
</div>
<nav class="site-nav">
<ul id="menu" class="menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section">
<i class="menu-item-icon fa fa-fw fa-home"></i> <br />
首页
</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives" rel="section">
<i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
归档
</a>
</li>
<li class="menu-item menu-item-tags">
<a href="/tags" rel="section">
<i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
标签
</a>
</li>
</ul>
</nav>
</div>
</header>
<main id="main" class="main">
<div class="main-inner">
<div class="content-wrap">
<div id="content" class="content">
<section id="posts" class="posts-expand">
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/07/05/quick-guide-for-RxSwift-four/" itemprop="url">
RxSwift快速指南(四)
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time itemprop="dateCreated" datetime="2016-07-05T21:59:00+08:00" content="2016-07-05">
2016-07-05
</time>
</span>
<span class="post-comments-count">
|
<a href="/2016/07/05/quick-guide-for-RxSwift-four/#comments" itemprop="discussionUrl">
<span class="post-comments-count ds-thread-count" data-thread-key="2016/07/05/quick-guide-for-RxSwift-four/" itemprop="commentsCount"></span>
</a>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="Combine"><a href="#Combine" class="headerlink" title="Combine"></a>Combine</h1><p>有时数据源并不只一个,比如用户登录,我们需要将用户名和密码进行合并验证,这时我们可以使用RxSwift为我们提供的合并,<code>combineLatest</code>, <code>merge</code>, <code>startWith</code>, <code>switchLatest</code>和<code>zip</code>等。</p>
<h2 id="combineLatest"><a href="#combineLatest" class="headerlink" title="combineLatest"></a>combineLatest</h2><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">example(<span class="string">"combineLatest"</span>) {</span><br><span class="line"><span class="keyword">let</span> disposeBag = <span class="type">DisposeBag</span>()</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> stringSubject = <span class="type">PublishSubject</span><<span class="type">String</span>>()</span><br><span class="line"><span class="keyword">let</span> intSubject = <span class="type">PublishSubject</span><<span class="type">Int</span>>()</span><br><span class="line"></span><br><span class="line"><span class="type">Observable</span>.combineLatest(stringSubject, intSubject) { stringElement, intElement <span class="keyword">in</span></span><br><span class="line"> <span class="string">"<span class="subst">\(stringElement)</span> <span class="subst">\(intElement)</span>"</span></span><br><span class="line"> }</span><br><span class="line"> .subscribeNext { <span class="built_in">print</span>($<span class="number">0</span>) }</span><br><span class="line"> .addDisposableTo(disposeBag)</span><br><span class="line"></span><br><span class="line">stringSubject.onNext(<span class="string">"A"</span>)</span><br><span class="line">stringSubject.onNext(<span class="string">"B"</span>)</span><br><span class="line">intSubject.onNext(<span class="number">1</span>)</span><br><span class="line">intSubject.onNext(<span class="number">2</span>)</span><br><span class="line">stringSubject.onNext(<span class="string">"AB"</span>)</span><br><span class="line">intSubject.onNext(<span class="number">3</span>)</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><code>combineLatest</code>和<code>zip</code>比较像,通过一个resultSelector的closure,将不同队列中的Element进行合并,最终队列Element的数量是当所有队列都有值后,这些队列在出现的Element数量加一。</p>
<h2 id="merge"><a href="#merge" class="headerlink" title="merge"></a>merge</h2><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> disposeBag = <span class="type">DisposeBag</span>()</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> subject1 = <span class="type">PublishSubject</span><<span class="type">String</span>>()</span><br><span class="line"><span class="keyword">let</span> subject2 = <span class="type">PublishSubject</span><<span class="type">String</span>>()</span><br><span class="line"></span><br><span class="line"><span class="type">Observable</span>.of(subject1, subject2)</span><br><span class="line"> .merge()</span><br><span class="line"> .subscribeNext { <span class="built_in">print</span>($<span class="number">0</span>) }</span><br><span class="line"> .addDisposableTo(disposeBag)</span><br><span class="line"></span><br><span class="line">subject1.onNext(<span class="string">"A"</span>)</span><br><span class="line">subject1.onNext(<span class="string">"B"</span>)</span><br><span class="line">subject2.onNext(<span class="string">"1"</span>)</span><br><span class="line">subject2.onNext(<span class="string">"2"</span>)</span><br><span class="line">subject1.onNext(<span class="string">"AB"</span>)</span><br><span class="line">subject2.onNext(<span class="string">"3"</span>)</span><br></pre></td></tr></table></figure>
<p><code>merge</code>将所有队列中的元素按照出现的顺序合并到一个队列中去。</p>
<h2 id="startWith"><a href="#startWith" class="headerlink" title="startWith"></a>startWith</h2><p><code>startWith</code>用于在一个队列前加入一些Elements。</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> disposeBag = <span class="type">DisposeBag</span>()</span><br><span class="line"></span><br><span class="line"><span class="type">Observable</span>.of(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>)</span><br><span class="line"> .startWith(<span class="string">"A"</span>)</span><br><span class="line"> .startWith(<span class="string">"B"</span>, <span class="string">"C"</span>, <span class="string">"D"</span>)</span><br><span class="line"> .subscribeNext { <span class="built_in">print</span>($<span class="number">0</span>) }</span><br><span class="line"> .addDisposableTo(disposeBag)</span><br></pre></td></tr></table></figure>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">func</span> <span class="title">startWith</span><span class="params">(elements: E ...)</span></span> -> <span class="type">Observable</span><<span class="type">E</span>> {</span><br><span class="line"> <span class="keyword">return</span> <span class="type">StartWith</span>(source: <span class="keyword">self</span>.asObservable(), elements: elements)</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><code>elements</code>这里是一个可变参数,可接受一个或者多个元素,需要注意的是如果在Observable中加入debug信息,后加入的Element并不在Next Event里,这可能会给你的调试带来一些麻烦,可能这是一个Debug和Producer在一起的bug。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">--- startWith example ---</span><br><span class="line">B</span><br><span class="line">C</span><br><span class="line">D</span><br><span class="line">A</span><br><span class="line">2016-07-06 19:40:31.382: startWith -> subscribed</span><br><span class="line">2016-07-06 19:40:31.383: startWith -> Event Next(1)</span><br><span class="line">1</span><br><span class="line">2016-07-06 19:40:31.383: startWith -> Event Next(2)</span><br><span class="line">2</span><br><span class="line">2016-07-06 19:40:31.383: startWith -> Event Next(3)</span><br><span class="line">3</span><br><span class="line">2016-07-06 19:40:31.384: startWith -> Event Next(4)</span><br><span class="line">4</span><br><span class="line">2016-07-06 19:40:31.384: startWith -> Event Completed</span><br><span class="line">2016-07-06 19:40:31.384: startWith -> disposed</span><br></pre></td></tr></table></figure>
<h2 id="switchLatest"><a href="#switchLatest" class="headerlink" title="switchLatest"></a>switchLatest</h2><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> disposeBag = <span class="type">DisposeBag</span>()</span><br><span class="line"></span><br><span class="line"><span class="type">Observable</span>.range(start: <span class="number">0</span>, <span class="built_in">count</span>: <span class="number">3</span>)</span><br><span class="line"> .<span class="built_in">map</span> { <span class="type">Observable</span>.range(start: $<span class="number">0</span>, <span class="built_in">count</span>: <span class="number">3</span>) }</span><br><span class="line"> .switchLatest()</span><br><span class="line"> .subscribeNext { <span class="built_in">print</span>($<span class="number">0</span>) }</span><br><span class="line"> .addDisposableTo(disposeBag)</span><br></pre></td></tr></table></figure>
<p>map后再switchLatest其实和flatMapLatest的结果是一样的,需要理解的是switch队列以后,以前队列的Element将不在发送。</p>
<img src="/2016/07/05/quick-guide-for-RxSwift-four/switchLatest.png" alt="switchLatest" title="switchLatest">
<h2 id="zip"><a href="#zip" class="headerlink" title="zip"></a>zip</h2><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> disposeBag = <span class="type">DisposeBag</span>()</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> range = <span class="type">Observable</span>.range(start: <span class="number">0</span>, <span class="built_in">count</span>: <span class="number">5</span>);</span><br><span class="line"><span class="type">Observable</span>.<span class="built_in">zip</span>(range, range.skip(<span class="number">1</span>), range.skip(<span class="number">2</span>)) { <span class="string">"<span class="subst">\($<span class="number">0</span>)</span>:<span class="subst">\($<span class="number">1</span>)</span>:<span class="subst">\($<span class="number">2</span>)</span>"</span> }</span><br><span class="line"> .subscribeNext { <span class="built_in">print</span>($<span class="number">0</span>) }</span><br><span class="line"> .addDisposableTo(disposeBag)</span><br></pre></td></tr></table></figure>
<p><code>zip</code>可以和<code>combineLatest</code>对比理解,zip每次在每个队列中取一个元素进行处理,元素在对应的队列中index是一样,产生的Element数量和最少的队列Element数量一样。</p>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/07/03/quick-guide-for-RxSwift-three/" itemprop="url">
RxSwift快速指南(三)
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time itemprop="dateCreated" datetime="2016-07-03T14:26:33+08:00" content="2016-07-03">
2016-07-03
</time>
</span>
<span class="post-comments-count">
|
<a href="/2016/07/03/quick-guide-for-RxSwift-three/#comments" itemprop="discussionUrl">
<span class="post-comments-count ds-thread-count" data-thread-key="2016/07/03/quick-guide-for-RxSwift-three/" itemprop="commentsCount"></span>
</a>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="Filter"><a href="#Filter" class="headerlink" title="Filter"></a>Filter</h1><p>Filter的操作即为过滤,是将Observable队列中不需要的Element去掉,RxSwift为我们提供了例如<code>debounce \ throttle</code>, <code>distinctUntilChanged</code>, <code>elementAt</code>, <code>filter</code>, <code>sample</code>, <code>skip</code>, <code>take</code>, <code>takeLast</code>和<code>single</code>的方法。</p>
<h2 id="debounce"><a href="#debounce" class="headerlink" title="debounce"></a>debounce</h2><p>debounce和throttle其实是一样的,队列中的元素如果和下一个元素的间隔小于了指定的时间间隔,那么这个元素将被过滤掉。</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> times = [</span><br><span class="line"> [ <span class="string">"value"</span>: <span class="number">0</span>, <span class="string">"time"</span>: <span class="number">0.1</span> ],</span><br><span class="line"> [ <span class="string">"value"</span>: <span class="number">1</span>, <span class="string">"time"</span>: <span class="number">0.4</span> ],</span><br><span class="line"> [ <span class="string">"value"</span>: <span class="number">2</span>, <span class="string">"time"</span>: <span class="number">0.6</span> ],</span><br><span class="line"> [ <span class="string">"value"</span>: <span class="number">3</span>, <span class="string">"time"</span>: <span class="number">0.8</span> ],</span><br><span class="line"> [ <span class="string">"value"</span>: <span class="number">4</span>, <span class="string">"time"</span>: <span class="number">1.0</span> ],</span><br><span class="line"> [ <span class="string">"value"</span>: <span class="number">5</span>, <span class="string">"time"</span>: <span class="number">1.4</span> ]</span><br><span class="line">];</span><br><span class="line"></span><br><span class="line">times.toObservable()</span><br><span class="line"> .flatMap { item <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">return</span> <span class="type">Observable</span>.of(item[<span class="string">"value"</span>]!)</span><br><span class="line"> .delaySubscription(<span class="type">Double</span>(item[<span class="string">"time"</span>]!), scheduler: <span class="type">MainScheduler</span>.instance)</span><br><span class="line"> }</span><br><span class="line"> .debounce(<span class="number">0.2</span>, scheduler: <span class="type">MainScheduler</span>.instance)</span><br><span class="line"> .subscribe { <span class="built_in">print</span>($<span class="number">0</span>) }</span><br></pre></td></tr></table></figure>
<p>代码输出结果:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Next(0.0)</span><br><span class="line">Next(4.0)</span><br><span class="line">Next(5.0)</span><br><span class="line">Completed</span><br></pre></td></tr></table></figure>
<h2 id="distinctUntilChanged"><a href="#distinctUntilChanged" class="headerlink" title="distinctUntilChanged"></a>distinctUntilChanged</h2><p>如果队列中出现相同Element,将被过滤掉。</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> disposeBag = <span class="type">DisposeBag</span>()</span><br><span class="line"></span><br><span class="line"><span class="type">Observable</span>.of(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">3</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>)</span><br><span class="line"> .distinctUntilChanged()</span><br><span class="line"> .subscribe { <span class="built_in">print</span>($<span class="number">0</span>) }</span><br><span class="line"> .addDisposableTo(disposeBag)</span><br></pre></td></tr></table></figure>
<h2 id="filter"><a href="#filter" class="headerlink" title="filter"></a>filter</h2><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> disposeBag = <span class="type">DisposeBag</span>()</span><br><span class="line"></span><br><span class="line"><span class="type">Observable</span>.of(</span><br><span class="line"> <span class="string">"aa"</span>, <span class="string">"ab"</span>, <span class="string">"ac"</span>,</span><br><span class="line"> <span class="string">"bb"</span>, <span class="string">"aa"</span>, <span class="string">"cc"</span>,</span><br><span class="line"> <span class="string">"ca"</span>, <span class="string">"bc"</span>, <span class="string">"aa"</span>)</span><br><span class="line"> .<span class="built_in">filter</span> { $<span class="number">0</span> == <span class="string">"aa"</span> }</span><br><span class="line"> .subscribeNext { <span class="built_in">print</span>($<span class="number">0</span>) }</span><br><span class="line"> .addDisposableTo(disposeBag)</span><br></pre></td></tr></table></figure>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">func</span> <span class="title">filter</span><span class="params">(predicate: <span class="params">(E)</span></span></span> <span class="keyword">throws</span> -> <span class="type">Bool</span>) -> <span class="type">Observable</span><<span class="type">E</span>> {</span><br><span class="line"> <span class="keyword">return</span> <span class="type">Filter</span>(source: asObservable(), predicate: predicate)</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>和其他FP中的filter一样,predicate返回值为布尔值,true则保留这个Element,返回false时这个Element将被过滤掉。</p>
<h2 id="sample"><a href="#sample" class="headerlink" title="sample"></a>sample</h2><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> tap = <span class="type">Observable</span><<span class="type">NSInteger</span>>.interval(<span class="number">0.6</span>, scheduler: <span class="type">SerialDispatchQueueScheduler</span>(internalSerialQueueName: <span class="string">"tap"</span>))</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> timerSubscribe = <span class="type">Observable</span><<span class="type">NSInteger</span>>.interval(<span class="number">0.1</span>, scheduler: <span class="type">SerialDispatchQueueScheduler</span>(internalSerialQueueName: <span class="string">"timer"</span>))</span><br><span class="line"> .sample(tap)</span><br><span class="line"> .subscribeNext({ msecs -> <span class="type">Void</span> <span class="keyword">in</span></span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"<span class="subst">\(msecs)</span>00ms"</span>)</span><br><span class="line"> })</span><br><span class="line"></span><br><span class="line"><span class="type">NSThread</span>.sleepForTimeInterval(<span class="number">4</span>)</span><br><span class="line">timerSubscribe.dispose()</span><br></pre></td></tr></table></figure>
<p>sample字面意思是简化,通过参数的队列来简化源队列,在官方的Example中没有找到对应例子,官方的描述也是让人想不出来这个方法适用于什么地方,直到看这个<a href="http://rx-marin.com/post/rxswift-rxcocoa-sample-split-laps-timer/" target="_blank" rel="external">这篇博客</a>才豁然开朗,需注意的是,参数队列中的元素值将被忽略。</p>
<img src="/2016/07/03/quick-guide-for-RxSwift-three/sample.png" alt="sample" title="sample">
<h2 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h2><p>其他方法都比较简单,通过方法名都能知道在干什么,官方的playground中也能找到对应的实例,这里就不一一阐述了。</p>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/06/27/quick-guide-for-RxSwift-two/" itemprop="url">
RxSwift快速指南(二)
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time itemprop="dateCreated" datetime="2016-06-27T23:26:10+08:00" content="2016-06-27">
2016-06-27
</time>
</span>
<span class="post-comments-count">
|
<a href="/2016/06/27/quick-guide-for-RxSwift-two/#comments" itemprop="discussionUrl">
<span class="post-comments-count ds-thread-count" data-thread-key="2016/06/27/quick-guide-for-RxSwift-two/" itemprop="commentsCount"></span>
</a>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="Transform"><a href="#Transform" class="headerlink" title="Transform"></a>Transform</h1><p>接触过FP的应该都知道map,RxSwift也提供对应的方法将Element进行变形,主要的方法有<code>buffer</code>, <code>flatMap</code>, <code>flatMapFirst</code>, <code>flatMapLatest</code>, <code>map</code>, <code>scan</code>和<code>window</code>, 用的比较多的是<code>map</code>和<code>flatMap</code>。</p>
<h2 id="map"><a href="#map" class="headerlink" title="map"></a>map</h2><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> disposeBag = <span class="type">DisposeBag</span>()</span><br><span class="line"><span class="type">Observable</span>.of(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>)</span><br><span class="line"> .<span class="built_in">map</span> { <span class="string">"<span class="subst">\($<span class="number">0</span>)</span><span class="subst">\($<span class="number">0</span>)</span>"</span> }</span><br><span class="line"> .subscribeNext { <span class="built_in">print</span>($<span class="number">0</span>) }</span><br><span class="line"> .addDisposableTo(disposeBag)</span><br></pre></td></tr></table></figure>
<p>根据<code>map</code>的定义:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">func</span> <span class="title">map</span><R><span class="params">(selector: E <span class="keyword">throws</span> -> R)</span></span> -> <span class="type">Observable</span><<span class="type">R</span>> {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">self</span>.asObservable().composeMap(selector)</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><code>selector</code>这个closure负责将E转换为R,而E这里被定义为Observable.of(1, 2, 3)的Int,每个元素会被转换为String。</p>
<h2 id="flatMap"><a href="#flatMap" class="headerlink" title="flatMap"></a>flatMap</h2><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> disposeBag = <span class="type">DisposeBag</span>()</span><br><span class="line"><span class="keyword">let</span> sequenceInt = <span class="type">Observable</span>.of(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>)</span><br><span class="line"><span class="keyword">let</span> sequenceString = <span class="type">Observable</span>.of(<span class="string">"A"</span>, <span class="string">"B"</span>, <span class="string">"C"</span>, <span class="string">"D"</span>)</span><br><span class="line"></span><br><span class="line">sequenceInt.flatMap { <span class="number">_</span> <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">return</span> sequenceString</span><br><span class="line"> }</span><br><span class="line"> .subscribe { <span class="built_in">print</span>($<span class="number">0</span>) }</span><br><span class="line"> .addDisposableTo(disposeBag)</span><br></pre></td></tr></table></figure>
<p><code>flatMap</code>的定义:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">func</span> <span class="title">flatMap</span><O: ObservableConvertibleType><span class="params">(selector: <span class="params">(E)</span></span></span> <span class="keyword">throws</span> -> <span class="type">O</span>) -> <span class="type">Observable</span><<span class="type">O</span>.<span class="type">E</span>> {</span><br><span class="line"> <span class="keyword">return</span> <span class="type">FlatMap</span>(source: asObservable(), selector: selector)</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>来看看Rx官方给出的描述:</p>
<table>
<thead>
<tr>
<th>map</th>
<th>flatMap</th>
</tr>
</thead>
<tbody>
<tr>
<td>Transform the items emitted by an Observable by applying a function to each item</td>
<td>Transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable</td>
</tr>
</tbody>
</table>
<p><code>map</code>和<code>flatMap</code>的区别在于<code>map</code>的selector将用于Observable中的每一个Element,操作完成后,Element的数量和源Observable中的是一样的,而<code>flatMap</code>的selector的调用次数和源Element数量一致,但是由于selector的返回值为一个Observable,所以在操作完成后,得到的Elements为源Element数量*selector返回的Observable的Element数量,然后将所有Element放入一个Observable中,类似于<code>[[1, 2], [2, 3], [3, 4]]</code> -> <code>[1, 2, 2, 3, 3, 4]</code>。</p>
<img src="/2016/06/27/quick-guide-for-RxSwift-two/flatMap.png" alt="flatMap" title="flatMap">
<h2 id="flatMapLatest"><a href="#flatMapLatest" class="headerlink" title="flatMapLatest"></a>flatMapLatest</h2><p>比起<code>map</code>和<code>flatMap</code>,要稍微难理解一点:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> disposeBag = <span class="type">DisposeBag</span>()</span><br><span class="line"></span><br><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>].toObservable()</span><br><span class="line"> .flatMapLatest { value <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">return</span> [<span class="string">"<span class="subst">\(value)</span>a"</span>, <span class="string">"<span class="subst">\(value)</span>b"</span>].toObservable()</span><br><span class="line"> }</span><br><span class="line"> .subscribe { <span class="built_in">print</span>($<span class="number">0</span>) }</span><br><span class="line"> .addDisposableTo(disposeBag)</span><br></pre></td></tr></table></figure>
<p>根据<a href="https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/flatmaplatest.md" target="_blank" rel="external">RxJS flatMapLatest</a>这个代码期望的结果是(RxSwift和Rx系的其他语句具有相似接口,其中RxJava对应的方法是switchMap,在<a href="https://github.com/Reactive-Extensions/RxJS/blob/master/src/core/perf/operators/flatmaplatest.js" target="_blank" rel="external">RxJS Source Code</a>也能发现其实它和switchMap是一个函数):</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Next(1a)</span><br><span class="line">Next(2a)</span><br><span class="line">Next(3a)</span><br><span class="line">Next(3b)</span><br><span class="line">Completed</span><br></pre></td></tr></table></figure>
<p>但是实际上得到的输出结果是:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Next(1a)</span><br><span class="line">Next(1b)</span><br><span class="line">Next(2a)</span><br><span class="line">Next(2b)</span><br><span class="line">Next(3a)</span><br><span class="line">Next(3b)</span><br><span class="line">Completed</span><br></pre></td></tr></table></figure>
<p>出现这种情况的原因在github的<a href="https://github.com/ReactiveX/RxSwift/blob/master/Documentation/GettingStarted.md#creating-your-own-observable-aka-observable-sequence" target="_blank" rel="external">Get Start</a>有解释,问题出现在selector中的<code>toObservable</code>,它的实现使用了<code>Sequence</code>:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">func</span> <span class="title">toObservable</span><span class="params">(scheduler: ImmediateSchedulerType? = <span class="literal">nil</span>)</span></span> -> <span class="type">Observable</span><<span class="type">Generator</span>.<span class="type">Element</span>> {</span><br><span class="line"> <span class="keyword">return</span> <span class="type">Sequence</span>(elements: <span class="keyword">self</span>, scheduler: scheduler)</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><code>Sequence</code>其实是一个同步队列的实现,在<code>subscribe</code>调用前会生成Next和Completed,因为无论哪种disposable被返回,生成elements的过程都不能被打断。在这种情况下,<code>flatMapLatest</code>和<code>flatMap</code>的输出结果一样。</p>
<p>期望的版本:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> disposeBag = <span class="type">DisposeBag</span>()</span><br><span class="line"><span class="keyword">var</span> charValues: [<span class="type">Variable</span><<span class="type">Character</span>>] = [<span class="type">Variable</span>(<span class="string">"a"</span>), <span class="type">Variable</span>(<span class="string">"a"</span>), <span class="type">Variable</span>(<span class="string">"a"</span>)]</span><br><span class="line"></span><br><span class="line">[<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>].toObservable()</span><br><span class="line"> .flatMapLatest { value -> <span class="type">Observable</span><<span class="type">Character</span>> <span class="keyword">in</span></span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"Int value: <span class="subst">\(value)</span>"</span>)</span><br><span class="line"> <span class="keyword">return</span> charValues[value].asObservable()</span><br><span class="line"> }</span><br><span class="line"> .subscribe { <span class="built_in">print</span>($<span class="number">0</span>) }</span><br><span class="line"> .addDisposableTo(disposeBag)</span><br><span class="line"></span><br><span class="line">charValues[<span class="number">2</span>].value = <span class="string">"b"</span></span><br><span class="line">charValues[<span class="number">0</span>].value = <span class="string">"c"</span> <span class="comment">// nothing happen</span></span><br><span class="line">charValues[<span class="number">1</span>].value = <span class="string">"d"</span> <span class="comment">// nothing happen</span></span><br></pre></td></tr></table></figure>
<img src="/2016/06/27/quick-guide-for-RxSwift-two/flatMapLatest.png" alt="flatMapLatest" title="flatMapLatest">
<p>和<code>flatMap</code>一样,<code>flatMapLatest</code>也会新生成一个Observable的队列,但不同的是它不会合并所有的新Observable中的Element,它会switch到最后一个Observable上(<code>switchMap</code>这个名字感觉更容易让人理解一点),先前建立的Observable将不再被监听,所以代码中charValues只有最后一个Observable还在被subscribe。</p>
<h2 id="scan"><a href="#scan" class="headerlink" title="scan"></a>scan</h2><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> disposeBag = <span class="type">DisposeBag</span>()</span><br><span class="line"><span class="type">Observable</span>.range(start: <span class="number">1</span>, <span class="built_in">count</span>: <span class="number">3</span>)</span><br><span class="line"> .scan(<span class="number">0</span>) { $<span class="number">0</span> + $<span class="number">1</span> }</span><br><span class="line"> .subscribe { <span class="built_in">print</span>($<span class="number">0</span>) }</span><br><span class="line"> .addDisposableTo(disposeBag)</span><br></pre></td></tr></table></figure>
<p><code>scan</code>和swift的原生方法reduce很类似(区别在于scan后的Element数量和源Element数量一致,但是reduce只会返回一个Element),在Observable+Single中我们能够找到它的定义:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">func</span> <span class="title">scan</span><A><span class="params">(seed: A, accumulator: <span class="params">(A, E)</span></span></span> <span class="keyword">throws</span> -> <span class="type">A</span>) -> <span class="type">Observable</span><<span class="type">A</span>> {</span><br><span class="line"> <span class="keyword">return</span> <span class="type">Scan</span>(source: <span class="keyword">self</span>.asObservable(), seed: seed, accumulator: accumulator)</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><code>seed</code>的scan开始的初始值,<code>accumulator</code>的第一个参数为上一次操作的返回值,第二个参数为Observable队列中的Element,然后返回处理结果。</p>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/06/24/quick-guide-for-RxSwift-one/" itemprop="url">
RxSwift快速指南(一)
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time itemprop="dateCreated" datetime="2016-06-24T19:25:02+08:00" content="2016-06-24">
2016-06-24
</time>
</span>
<span class="post-comments-count">
|
<a href="/2016/06/24/quick-guide-for-RxSwift-one/#comments" itemprop="discussionUrl">
<span class="post-comments-count ds-thread-count" data-thread-key="2016/06/24/quick-guide-for-RxSwift-one/" itemprop="commentsCount"></span>
</a>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h1><p>每个Observable队列都仅仅是一个简单的队列,Observable比Swift中的SequenceType优秀在于它能接受异步的元素,这是RxSwift的核心概念。</p>
<h2 id="Event"><a href="#Event" class="headerlink" title="Event"></a>Event</h2><p>队列的语法: <code>Next* (Error | Completed)?</code></p>
<p>Event是一个泛型枚举,一个队列中可以有0个或者多个Next元素,当队列中出现Error和Completed元素时,队列将不再接受Next元素。</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">enum</span> <span class="title">Event</span><<span class="title">Element</span>> </span>{</span><br><span class="line"> <span class="keyword">case</span> <span class="type">Next</span>(<span class="type">Element</span>)</span><br><span class="line"> <span class="keyword">case</span> <span class="type">Error</span>(<span class="type">ErrorType</span>)</span><br><span class="line"> <span class="keyword">case</span> <span class="type">Completed</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="创建一个Observable-aka-observable-sequence"><a href="#创建一个Observable-aka-observable-sequence" class="headerlink" title="创建一个Observable(aka observable sequence)"></a>创建一个Observable(aka observable sequence)</h2><p>在Observable+Creation中,RxSwift定义了很多帮助创建Observable的方法,例如<code>create</code>, <code>empty</code>, <code>never</code>, <code>just</code>, <code>error</code>, <code>of</code>, <code>deferred</code>, <code>generate</code>, <code>repeatElement</code>和<code>using</code>, 以及对SequenceType和Array的扩展方法<code>toObservable</code>。</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">myJust</span><E><span class="params">(element: E)</span></span> -> <span class="type">Observable</span><<span class="type">E</span>> {</span><br><span class="line"> <span class="keyword">return</span> <span class="type">Observable</span>.create { observer <span class="keyword">in</span></span><br><span class="line"> observer.on(.<span class="type">Next</span>(element))</span><br><span class="line"> observer.on(.<span class="type">Completed</span>)</span><br><span class="line"> <span class="keyword">return</span> <span class="type">NopDisposable</span>.instance</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>这里通过尾随闭包(Trailing Closures)来创建了一个Observable,create方法的定义是:</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">func</span> <span class="title">create</span><span class="params">(subscribe: <span class="params">(AnyObserver<E>)</span></span></span> -> <span class="type">Disposable</span>) -> <span class="type">Observable</span><<span class="type">E</span>> {</span><br><span class="line"> <span class="keyword">return</span> <span class="type">AnonymousObservable</span>(subscribe)</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>这里subscribe其实是一个handler,接受一个Observer,返回一个Disposable对象,并作为AnonymousObservable的init参数传入。<code>AnyObserver<Element></code>实现了<code>ObserverType</code>协议,我们在该handler内,将<code>Event</code>通过<code>on</code>发送到队列中去,最后返回的Disposable,Disposable在Observable被<code>subscribe</code>后被返回,用作Observable的终止。</p>
<h2 id="订阅一个Observable"><a href="#订阅一个Observable" class="headerlink" title="订阅一个Observable"></a>订阅一个Observable</h2><p>在Observable被创建后,我们会得到一个Observable,它实现了<code>ObservableType</code>协议,在Observable+Extensions中,可以发现一些用于订阅的方法:<code>subscribe</code>, <code>subscribeNext</code>, <code>subscribeError</code>和<code>subscribeCompleted</code>。被创建的Observable是不会执行任何代码的,因为它只定义了Observable怎么被创建起来,只有在它被subscribe之后,队列才会真正被创建。</p>
<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">func</span> <span class="title">subscribeNext</span><span class="params">(onNext: <span class="params">(E)</span></span></span> -> <span class="type">Void</span>) -> <span class="type">Disposable</span> {</span><br><span class="line"> <span class="keyword">let</span> observer = <span class="type">AnonymousObserver</span><<span class="type">E</span>> { e <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">case</span> .<span class="type">Next</span>(<span class="keyword">let</span> value) = e {</span><br><span class="line"> onNext(value)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">self</span>.subscribeSafe(observer)</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="Observable的终止"><a href="#Observable的终止" class="headerlink" title="Observable的终止"></a>Observable的终止</h2><p>在一个subscription上调用<code>dispose</code>将终止一个被观察的队列,在create时定义的Disposable的销毁代码会被执行。</p>
<h1 id="生命周期"><a href="#生命周期" class="headerlink" title="生命周期"></a>生命周期</h1><p>在基本概念中,我们接触到了Event,Observable和Observer,他们的生命周期如图所示:</p>
<img src="/2016/06/24/quick-guide-for-RxSwift-one/RxSwift.001.png" alt="RxSwift life cycle" title="RxSwift life cycle">
<blockquote>
<p>本节仅介绍了RxSwift中几个重要的概念和他们是怎么协同工作的,下一节将细化Observable的transform, filter和combine。</p>
</blockquote>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2013/08/04/continuous-integration/" itemprop="url">
Continuous Integration
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time itemprop="dateCreated" datetime="2013-08-04T20:11:00+08:00" content="2013-08-04">
2013-08-04
</time>
</span>
<span class="post-comments-count">
|
<a href="/2013/08/04/continuous-integration/#comments" itemprop="discussionUrl">
<span class="post-comments-count ds-thread-count" data-thread-key="2013/08/04/continuous-integration/" itemprop="commentsCount"></span>
</a>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h2 id="持续集成能干什么"><a href="#持续集成能干什么" class="headerlink" title="持续集成能干什么"></a>持续集成能干什么</h2><hr>
<p>在以往传统的开发中,集成往往被放在开发周期的后期–联调,这样的后果就是在开发过程中得到一个不可预知的联调阶段。联调阶段往往在传统开发模式中最为艰苦的一个阶段。</p>
<h3 id="联调中主要问题"><a href="#联调中主要问题" class="headerlink" title="联调中主要问题"></a>联调中主要问题</h3><ul>
<li>在开发初期没有考虑好的架构、接口等问题。</li>
<li>由于单独模块开发时可能使用不相同的运行环境,集成后环境不统一,造成的程序运行不稳当。</li>
</ul>
<p>持续集成的出现,旨意解决在联调中出现问题,持续集成,将联调进行拆分,分成步骤很小的集成,分散到整个开发过程中,而不是把集成放到软件开发的末期。</p>
<h3 id="持续集成的好处"><a href="#持续集成的好处" class="headerlink" title="持续集成的好处"></a>持续集成的好处</h3><ul>
<li>由于将集成放到了每个开发周期,一旦有集成的问题,能够及时的发现,并进行修复。</li>
<li>解决频繁部署的问题,可以及时的将测试版本交由客户,从而及时得到客户的反馈,保证开发的系统确实的用户所需要的。</li>
<li>由于每次集成后构建,都可以得到一个可运行的系统,从另一方面考虑,降低了客户的资金风险。</li>
<li>持续集成过程中使用到一些自动化构建测试大大降低了工作量,虽然初期需要花比较成的时间搭建持续集成环境,但是长远考虑,这是有利的。</li>
<li>持续集成,能够将项目的当前状况,及时反馈给每一个开发者,从而降低了开发过程中的交流成本。</li>
</ul>
<hr>
<h2 id="只维护一个源码仓库"><a href="#只维护一个源码仓库" class="headerlink" title="只维护一个源码仓库"></a>只维护一个源码仓库</h2><p>源代码管理系统现在多用分布式的git,需要注意是:需将所有文件都放进源代码管理系统,除了代码外,还需要将相关测试脚本,配置文件,数据库Schema,安装脚本,第三方库,甚至IDE的配置文件。以确保一个原则:<strong>任何人都可以找到一台干净的机器,做一次取出(checkout)动作,然后对系统执行一次完整的构建。</strong></p>
<p>使用同一个源码仓库的优势:</p>
<ul>
<li>使得每个协同工作的worker,都能快速的获得同样的、最新的代码,保证了<strong>集成的时效性</strong>,并能<strong>快速找出集成中出现的问题</strong>。</li>
<li>在开发过程中,如果需要增加worker,一次checkout就能让其马上立即得到可行的工作环境。</li>
</ul>
<hr>
<h2 id="使用持续集成构建"><a href="#使用持续集成构建" class="headerlink" title="使用持续集成构建"></a>使用持续集成构建</h2><h3 id="构建流程"><a href="#构建流程" class="headerlink" title="构建流程"></a>构建流程</h3><p><img src="http://www.infoq.com/resource/articles/ci-theory-practice/zh/resources/image1.png" alt="持续集成构建"></p>
<ul>
<li>更新<ul>
<li>每次在编辑代码前,需要从源码仓库中更新的代码,保证本地代码和代码仓库中的代码一致,为最新代码。</li>
</ul>
</li>
<li>编辑代码<ul>
<li>编辑代码完成尽量小的一个feature和对应的测试代码。</li>
</ul>
</li>
<li>本地构建<ul>
<li>对修改的代码进行自测试。</li>
</ul>
</li>
<li>更新<ul>
<li>再次从源码仓库中更新代码,因为在完成feature的同时,可能有其他人提交有新的代码。</li>
</ul>
</li>
<li>本地构建<ul>
<li>再次本地构建,保证新从仓库中检出的代码,和自己开发的feature没有集成错误。</li>
</ul>
</li>
<li>提交<ul>
<li>将代码提交到代码仓库。</li>
</ul>
</li>
<li>提交构建<ul>
<li>该步骤一般可又CI系统在代码提交后自动进行构建。</li>
</ul>
</li>
</ul>
<p>在构建中,一般分为这7个步骤。在一个步骤中,一般又可划分为多个小步骤。例如编辑代码步骤,在完成一个feature的时候,一般可将这个feature进行再拆分,每完成一个更小的feature后,使用git commit到local repository,保证代码在出现问题的时候,能够方便的进行git reset。</p>
<p>需要注意的步骤是step 6,setp 1~5因为都是local repository的操作,在做错后可以回滚,step 6会将本地代码push到remote repository中。所以,<strong>步骤6的前置本地构建,必须通过,通过所有测试,才能执行step 6.</strong></p>
<hr>
<h2 id="自动化build、自动化测试、自动化部署"><a href="#自动化build、自动化测试、自动化部署" class="headerlink" title="自动化build、自动化测试、自动化部署"></a>自动化build、自动化测试、自动化部署</h2><p>为项目选用合适的自动化build的工具是非常有必要的。</p>
<ul>
<li>可以把源码转变成一个可运行的系统这个过程简单化。</li>
<li>智能的build工具,可以检查源码之间的依赖项和修改项,选择性的编译,降低大型build的时间。</li>
<li>build脚本允许在不同的情况中build不同的target。</li>
</ul>
<p>自动化工具,可选用ant,maven,gradle等,IDE也会有对应的命令行工具,如MSBuild,xcodebuild等,当然还有一些工具如shell,PowerShell等,也会在自动化build中使用</p>
<p>开发者在开发时,可以使用IDE作为build工具,但是主build还是需要自动化的build工具,以保证他可以在开发服务器上运行。</p>
<ul>
<li>自动化测试,极限编程(Extreme Programming)和驱动测试开发(TDD)待续。。。</li>
<li>自动化部署待续。。。</li>
</ul>
<hr>
<h2 id="反馈和沟通"><a href="#反馈和沟通" class="headerlink" title="反馈和沟通"></a>反馈和沟通</h2><ul>
<li>及时向mainline提交代码,并在CI Master上重新构建</li>
<li>保持快速build</li>
<li>让每个人都能轻易获得最新的可执行文件</li>
<li>每个人都能看到进度</li>
</ul>
<p>以上这些步骤,都是为了一个目的:沟通。<br>沟通的角色有开发环节中的各个角色,以及和客户直接,每次DEV在开发完一个feature后,提交代码,在CI Master上进行重新构建,构建的结果将显示的公共的显示器上,以便于每个worker都能及时的查看到结果和进度。<br>保持快速build以及让每个人都能轻易获得最新的可执行文件,为了就是能够尽快从其他worker和客户那里获得反馈,保证了沟通的畅通性。</p>
<h3 id="分阶段构建(Staged-Build)"><a href="#分阶段构建(Staged-Build)" class="headerlink" title="分阶段构建(Staged Build)"></a>分阶段构建(Staged Build)</h3><ul>
<li>分离关注度不同的验证阶段。</li>
<li>构建流程可视化。</li>
<li>通过分阶段并发构建来缩短反馈周期。</li>
</ul>
<p>构建的过程一般会耗费很长时间,可将构建工作分为多个job,并行进行构建。这点在Jenkins中可轻松完成。</p>
<hr>
<h2 id="其他技巧"><a href="#其他技巧" class="headerlink" title="其他技巧"></a>其他技巧</h2><ul>
<li>在模拟生产环境中进行测试</li>
</ul>
<hr>
<h4 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h4><ul>
<li><a href="http://article.yeeyan.org/view/2251/94882" target="_blank" rel="external">持续集成(第二版)Martin Fowler</a></li>
<li><a href="http://www.infoq.com/cn/articles/ci-theory-practice" target="_blank" rel="external">持续集成理论和实践的新进展 肖鹏</a></li>
</ul>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
</section>
</div>
</div>
<div class="sidebar-toggle">
<div class="sidebar-toggle-line-wrap">
<span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
<span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
<span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
</div>
</div>
<aside id="sidebar" class="sidebar">
<div class="sidebar-inner">
<section class="site-overview sidebar-panel sidebar-panel-active ">
<div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
<img class="site-author-image" itemprop="image"
src="/images/avatar.gif"
alt="Zhen Tang" />
<p class="site-author-name" itemprop="name">Zhen Tang</p>
<p class="site-description motion-element" itemprop="description"></p>
</div>
<nav class="site-state motion-element">
<div class="site-state-item site-state-posts">
<a href="/archives">
<span class="site-state-item-count">5</span>
<span class="site-state-item-name">日志</span>
</a>
</div>
<div class="site-state-item site-state-tags">
<a href="/tags">
<span class="site-state-item-count">3</span>
<span class="site-state-item-name">标签</span>
</a>
</div>
</nav>
<div class="links-of-author motion-element">
<span class="links-of-author-item">
<a href="https://github.com/tangzhen" target="_blank" title="GitHub">
<i class="fa fa-fw fa-github"></i>
GitHub
</a>
</span>
<span class="links-of-author-item">
<a href="https://twitter.com/CloudTang" target="_blank" title="Twitter">
<i class="fa fa-fw fa-twitter"></i>
Twitter
</a>
</span>
<span class="links-of-author-item">
<a href="http://weibo.com/cloudtang" target="_blank" title="Weibo">
<i class="fa fa-fw fa-weibo"></i>
Weibo
</a>
</span>
</div>
</section>
</div>
</aside>