Repository navigation
Expand file tree
/
Copy pathatom.xml
More file actions
3923 lines (3523 loc) · 290 KB
/
Copy pathatom.xml
File metadata and controls
3923 lines (3523 loc) · 290 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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[时光 • 印记]]></title>
<link href="http://erikge.com/atom.xml" rel="self"/>
<link href="http://erikge.com/"/>
<updated>2014-07-24T17:21:58+08:00</updated>
<id>http://erikge.com/</id>
<author>
<name><![CDATA[erik ge]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[Swift的问题]]></title>
<link href="http://erikge.com/articles/SwiftTroubles"/>
<updated>2014-06-27T23:37:20+08:00</updated>
<id>http://erikge.com/articles/SwiftTroubles</id>
<content type="html"><![CDATA[<p>一种技术的出现解决了一些问题,同时也会带来更多的问题。正因为Swift的高级特性,也由此带来了一些复杂性和一些潜在的问题。</p>
<!--more-->
<h2 id="内存管理">内存管理</h2>
<p>Swift 使用自动引用计数(ARC)来自动管理内存。大部分情况下无需考虑内存的分配和释放,但要注意某些可能会导致内存问题的使用方法。</p>
<h3 id="arc工作原理">ARC工作原理</h3>
<p>强引用(strong reference):将一个类的实例赋值给一个属性或者常量或者变量,这个属性、常量或者变量就是这个实例的强引用。<br>
弱引用(weak reference):弱引用不会增加实例的引用计数,因此不会阻止 ARC 销毁被引用的实例。弱引用只能声明为可选类型(optional type)的变量。<br>
无主引用(unowned reference):无主引用也不强持有实例,但无主引用默认始终有值。无主引用只能定义为非可选类型(non-optional type)。</p>
<p>强引用还存在时,ARC不会释放这个实例。</p>
<h3 id="类实例间的强引用环">类实例间的强引用环</h3>
<p>两个实例相互引用对方作为自己的属性,彼此保持对方的强引用,这样就产生了强引用环,导致这两个实例永远不被释放。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">class</span> <span class="nc">Person</span> <span class="p">{</span>
</span><span class='line'> <span class="n">var</span> <span class="n">apartment</span><span class="p">:</span> <span class="n">Apartment</span><span class="err">?</span>
</span><span class='line'>
</span><span class='line'> <span class="n">deinit</span> <span class="p">{</span>
</span><span class='line'> <span class="n">println</span><span class="p">(</span><span class="s">"~~deinit Person"</span><span class="p">)</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="k">class</span> <span class="nc">Apartment</span> <span class="p">{</span>
</span><span class='line'> <span class="n">var</span> <span class="n">tenant</span><span class="p">:</span> <span class="n">Person</span><span class="err">?</span>
</span><span class='line'>
</span><span class='line'> <span class="n">deinit</span> <span class="p">{</span>
</span><span class='line'> <span class="n">println</span><span class="p">(</span><span class="s">"~~deinit Apartment"</span><span class="p">)</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="o">//</span> <span class="err">产生强引用环的情况</span>
</span><span class='line'><span class="n">var</span> <span class="n">foo</span><span class="p">:</span> <span class="n">Person</span><span class="err">?</span> <span class="o">=</span> <span class="n">Person</span><span class="p">()</span>
</span><span class='line'><span class="n">var</span> <span class="n">house</span><span class="p">:</span> <span class="n">Apartment</span><span class="err">?</span> <span class="o">=</span> <span class="n">Apartment</span><span class="p">()</span>
</span><span class='line'><span class="k">if</span> <span class="n">let</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">foo</span> <span class="p">{</span>
</span><span class='line'> <span class="n">tmp</span><span class="o">.</span><span class="n">apartment</span> <span class="o">=</span> <span class="n">house</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="n">house</span><span class="err">!</span><span class="o">.</span><span class="n">tenant</span> <span class="o">=</span> <span class="n">foo</span>
</span><span class='line'><span class="o">//</span> <span class="err">即便都置为</span><span class="n">nil</span><span class="err">也无法释放资源</span>
</span><span class='line'><span class="n">foo</span> <span class="o">=</span> <span class="n">nil</span>
</span><span class='line'><span class="n">house</span> <span class="o">=</span> <span class="n">nil</span>
</span></code></pre></td></tr></table></div></figure>
通过弱引用或无主引用来解决这个问题。如果生命周期中,引用(上例中的属性)有时有值,有时为nil,使用弱引用;如果始终有值,使用无主引用。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="o">//</span> <span class="err">通过弱引用解决</span>
</span><span class='line'><span class="k">class</span> <span class="nc">Apartment</span> <span class="p">{</span>
</span><span class='line'> <span class="n">weak</span> <span class="n">var</span> <span class="n">tenant</span><span class="p">:</span> <span class="n">Person</span><span class="err">?</span>
</span><span class='line'>
</span><span class='line'> <span class="n">deinit</span> <span class="p">{</span>
</span><span class='line'> <span class="n">println</span><span class="p">(</span><span class="s">"~~deinit Apartment"</span><span class="p">)</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="o">//</span> <span class="err">通过无主引用解决,如果</span><span class="n">house</span><span class="err">必须有主人的话</span>
</span><span class='line'><span class="k">class</span> <span class="nc">Person</span> <span class="p">{</span>
</span><span class='line'> <span class="n">var</span> <span class="n">apartment</span><span class="p">:</span> <span class="n">Apartment</span><span class="err">?</span>
</span><span class='line'>
</span><span class='line'> <span class="n">deinit</span> <span class="p">{</span>
</span><span class='line'> <span class="n">println</span><span class="p">(</span><span class="s">"~~deinit Person"</span><span class="p">)</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="k">class</span> <span class="nc">Apartment</span> <span class="p">{</span>
</span><span class='line'> <span class="n">unowned</span> <span class="n">var</span> <span class="n">tenant</span><span class="p">:</span> <span class="n">Person</span>
</span><span class='line'>
</span><span class='line'> <span class="n">init</span><span class="p">(</span><span class="n">person</span><span class="p">:</span> <span class="n">Person</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="n">tenant</span> <span class="o">=</span> <span class="n">person</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'> <span class="n">deinit</span> <span class="p">{</span>
</span><span class='line'> <span class="n">println</span><span class="p">(</span><span class="s">"~~deinit Apartment"</span><span class="p">)</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="n">var</span> <span class="n">foo</span><span class="p">:</span> <span class="n">Person</span><span class="err">?</span> <span class="o">=</span> <span class="n">Person</span><span class="p">()</span>
</span><span class='line'><span class="n">var</span> <span class="n">house</span><span class="p">:</span> <span class="n">Apartment</span><span class="err">?</span> <span class="o">=</span> <span class="n">Apartment</span><span class="p">(</span><span class="n">person</span><span class="p">:</span> <span class="n">foo</span><span class="err">!</span><span class="p">)</span>
</span><span class='line'><span class="o">//</span> <span class="err">相互引用</span>
</span><span class='line'><span class="k">if</span> <span class="n">let</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">foo</span> <span class="p">{</span>
</span><span class='line'> <span class="n">tmp</span><span class="o">.</span><span class="n">apartment</span> <span class="o">=</span> <span class="n">house</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="n">house</span><span class="err">!</span><span class="o">.</span><span class="n">tenant</span> <span class="o">=</span> <span class="n">foo</span><span class="err">!</span>
</span><span class='line'><span class="o">//</span> <span class="err">可以正常释放资源</span>
</span><span class='line'><span class="n">foo</span> <span class="o">=</span> <span class="n">nil</span>
</span><span class='line'><span class="n">house</span> <span class="o">=</span> <span class="n">nil</span>
</span></code></pre></td></tr></table></div></figure>
<p>如果无主引用的例子中,Person也一直有Apartment的话,Person中的apartment属性可以使用隐式展开的可选属性。</p>
<h3 id="闭包产生的强引用环">闭包产生的强引用环</h3>
<p>将一个闭包赋值给类实例的某个属性,并且这个闭包使用了实例(访问了实例的某个属性,或调用了实例的某个方法。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">class</span> <span class="nc">HTMLElement</span> <span class="p">{</span>
</span><span class='line'> <span class="n">let</span> <span class="n">name</span><span class="p">:</span> <span class="n">String</span>
</span><span class='line'> <span class="n">let</span> <span class="n">text</span><span class="p">:</span> <span class="n">String</span><span class="err">?</span>
</span><span class='line'>
</span><span class='line'> <span class="o">//</span> <span class="nd">@lazy</span><span class="err">保证初始化完成以及</span> <span class="bp">self</span> <span class="err">确实存在后</span><span class="p">,</span><span class="err">才能访问</span> <span class="n">lazy</span> <span class="err">属性</span>
</span><span class='line'> <span class="nd">@lazy</span> <span class="n">var</span> <span class="n">asHTML</span><span class="p">:</span> <span class="p">()</span> <span class="o">-></span> <span class="n">String</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'> <span class="k">if</span> <span class="n">let</span> <span class="n">text</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="s">"<(self.name)>(text)</(self.name)>"</span>
</span><span class='line'> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="s">"<(self.name) />"</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'> <span class="n">init</span><span class="p">(</span><span class="n">name</span><span class="p">:</span> <span class="n">String</span><span class="p">,</span> <span class="n">text</span><span class="p">:</span> <span class="n">String</span><span class="err">?</span> <span class="o">=</span> <span class="n">nil</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
</span><span class='line'> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="n">text</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'> <span class="n">deinit</span> <span class="p">{</span>
</span><span class='line'> <span class="n">println</span><span class="p">(</span><span class="s">"~~(name) deinit"</span><span class="p">)</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="n">var</span> <span class="n">html</span><span class="p">:</span> <span class="n">HTMLElement</span><span class="err">?</span> <span class="o">=</span> <span class="n">HTMLElement</span><span class="p">(</span><span class="n">name</span><span class="p">:</span> <span class="s">"head"</span><span class="p">)</span>
</span><span class='line'><span class="n">html</span><span class="err">?</span><span class="o">.</span><span class="n">asHTML</span><span class="p">()</span> <span class="o">//</span> <span class="err">使用闭包后产生了强引用环</span>
</span><span class='line'><span class="n">html</span> <span class="o">=</span> <span class="n">nil</span> <span class="o">//</span> <span class="n">HTMLElement</span><span class="err">实例和它的闭包都不会被销毁</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>可以通过闭包占用列表(closuer capture list)解决这个问题。Swift有如下约束:只要在闭包内使用 self 的成员,就要用 self.someProperty 或者
self.someMethod(而非只是 someProperty 或 someMethod)。这可以提醒你可能会不小心就占有了 self,导致强引用环。<br>
占有列表放置在闭包参数列表和返回类型之前。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="nd">@lazy</span> <span class="n">var</span> <span class="n">someClosure</span><span class="p">:</span> <span class="p">(</span><span class="n">Int</span><span class="p">,</span> <span class="n">String</span><span class="p">)</span> <span class="o">-></span> <span class="n">String</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'> <span class="p">[</span><span class="n">unowned</span> <span class="bp">self</span><span class="p">]</span> <span class="p">(</span><span class="n">index</span><span class="p">:</span> <span class="n">Int</span><span class="p">,</span> <span class="n">stringToProcess</span><span class="p">:</span> <span class="n">String</span><span class="p">)</span> <span class="o">-></span> <span class="n">String</span> <span class="ow">in</span>
</span><span class='line'> <span class="o">//</span> <span class="n">closure</span> <span class="n">body</span> <span class="n">goes</span> <span class="n">here</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="nd">@lazy</span> <span class="n">var</span> <span class="n">someClosure</span><span class="p">:</span> <span class="p">()</span> <span class="o">-></span> <span class="n">String</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'> <span class="p">[</span><span class="n">weak</span> <span class="bp">self</span><span class="p">]</span> <span class="ow">in</span>
</span><span class='line'> <span class="o">//</span> <span class="n">closure</span> <span class="n">body</span> <span class="n">goes</span> <span class="n">here</span>
</span><span class='line'> <span class="bp">self</span><span class="err">?</span><span class="o">.</span><span class="n">someProperty</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></p>
<h2 id="构造器">构造器</h2>
<p>构造器的部分也挺复杂的,类有一套构造器的规矩,扩展还可以添加新的构造器。其中有哪些问题需要注意?后续补充。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Swift的语法细节]]></title>
<link href="http://erikge.com/articles/SwiftSyntax"/>
<updated>2014-06-26T14:09:50+08:00</updated>
<id>http://erikge.com/articles/SwiftSyntax</id>
<content type="html"><![CDATA[<p>Swift类似脚本语言的高级语法特性,让Swift语言使用起来很直观,很符合人的直觉,整体感觉很简洁很舒服。使用不同编程语言的程序员都能找到熟悉的感觉,这种亲切感必将吸引更多的开发者。<br>
本文总结Swift中需要注意的语法细节,完整的语法说明参考苹果的官方文档<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/">The Swift Programming Language</a>。</p>
<!--more-->
<h2 id="变量名和常量名">变量名和常量名</h2>
<p>变量名、常量名可以使用Unicode字符,但不能包含连线符、制表符、数学符号、箭头和一些保留字符。
如果非要使用保留字符(如关键字)作为变量名,通过反引号(`)将字符包围(如`class`)。</p>
<h2 id="注释">注释</h2>
<p>注释可以嵌套,这样注释大段代码就方便了,只管开头结尾就好,不用担心里面的注释结束符捣乱了。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="o">/*</span> <span class="err">这是第一个多行注释的开头</span>
</span><span class='line'><span class="n">code</span> <span class="n">here</span>
</span><span class='line'><span class="o">/*</span> <span class="err">这是第二个被嵌套的多行注释</span> <span class="o">*/</span>
</span><span class='line'><span class="n">more</span> <span class="n">code</span> <span class="n">here</span>
</span><span class='line'><span class="err">这是第一个多行注释的结尾</span> <span class="o">*/</span>
</span></code></pre></td></tr></table></div></figure>
<h2 id="数学相关的操作">数学相关的操作</h2>
<h3 id="数值字面量">数值字面量</h3>
<p>整数字面量可以是十进制、二进制、八进制、十六进制
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">let</span> <span class="n">decimalInteger</span> <span class="o">=</span> <span class="mi">17</span>
</span><span class='line'><span class="n">let</span> <span class="n">binaryInteger</span> <span class="o">=</span> <span class="mi">0</span><span class="n">b10001</span> <span class="o">//</span> <span class="err">二进制的</span> <span class="mi">17</span>
</span><span class='line'><span class="n">let</span> <span class="n">octalInteger</span> <span class="o">=</span> <span class="mi">0</span><span class="n">o21</span> <span class="o">//</span> <span class="err">八进制的</span><span class="mi">17</span>
</span><span class='line'><span class="n">let</span> <span class="n">hexadecimalInteger</span> <span class="o">=</span> <span class="mh">0x11</span> <span class="o">//</span> <span class="err">十六进制的</span> <span class="mi">17</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>浮点字面量可以是十进制、十六进制。小数点两边必须有至少一个数字。有可选的指数,十进制为e、十六进制为p。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">let</span> <span class="n">decimalDouble</span> <span class="o">=</span> <span class="mf">12.1875</span>
</span><span class='line'><span class="n">let</span> <span class="n">exponentDouble</span> <span class="o">=</span> <span class="mf">1.21875e1</span> <span class="o">//</span> <span class="err">十进制指数的</span><span class="mf">12.1875</span>
</span><span class='line'><span class="n">let</span> <span class="n">hexadecimalDouble</span> <span class="o">=</span> <span class="mh">0xC</span><span class="o">.</span><span class="mi">3</span><span class="n">p0</span> <span class="o">//</span> <span class="err">十六进制指数的</span><span class="mf">12.1875</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>可以添加下划线提高可读性,不影响字面量的值。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">let</span> <span class="n">paddedDouble</span> <span class="o">=</span> <span class="mf">000123.456</span>
</span><span class='line'><span class="n">let</span> <span class="n">oneMillion</span> <span class="o">=</span> <span class="mi">1</span><span class="n"><em>000_000</span>
</span><span class='line'><span class="n">let</span> <span class="n">justOverOneMillion</span> <span class="o">=</span> <span class="mi">1</span><span class="n"></em>000_000</span><span class="o">.</span><span class="mo">000</span><span class="n">_000_1</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>可以通过typealias给类型起个更喜欢的别名,如<code>typealias AudioSample = UInt16</code>,这时AudioSample等价于UInt16。</p>
<h3 id="运算符">运算符</h3>
<p>求余运算符。<br>
% 为 求余运算符 或 取模运算符,可以对负数和浮点数操作。被求余数的符号被忽略。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="mi">9</span> <span class="o">%</span> <span class="mi">4</span> <span class="o">//</span> <span class="err">等于</span><span class="mi">1</span>
</span><span class='line'><span class="mi">9</span> <span class="o">%</span> <span class="o">-</span><span class="mi">4</span> <span class="o">//</span> <span class="err">和</span> <span class="mi">9</span> <span class="o">%</span> <span class="mi">4</span> <span class="err">等价,等于</span><span class="mi">1</span>
</span><span class='line'><span class="o">-</span><span class="mi">8</span> <span class="o">%</span> <span class="mf">2.5</span> <span class="o">//</span> <span class="err">等于</span><span class="o">-</span><span class="mf">0.5</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>区间运算符。<br>
<code>a...b</code>表示从a到b(包括 a 和 b)的所有值的闭区间;<code>a..b</code>表示包括a不包括b的前闭后开区间。</p>
<p>溢出运算符。<br>
Swift的数值计算默认是不可溢出的,溢出行为会被捕获并报error。Swift提供了一套以&开头的溢出运算符,包括<code>&+</code>, <code>&-</code>, <code>&*</code>, <code>&/</code>, <code>&%</code>。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">var</span> <span class="n">byte_min</span> <span class="o">=</span> <span class="n">Int8</span><span class="o">.</span><span class="n">max</span> <span class="o">&+</span> <span class="mi">1</span> <span class="o">//</span> <span class="o">-</span><span class="mi">128</span>
</span><span class='line'><span class="n">var</span> <span class="n">byte_max</span> <span class="o">=</span> <span class="n">Int8</span><span class="o">.</span><span class="n">min</span> <span class="o">&-</span> <span class="mi">1</span> <span class="o">//</span> <span class="mi">127</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>位运算符。<br>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">let</span> <span class="n">invert</span><span class="p">:</span> <span class="n">UInt8</span> <span class="o">=</span> <span class="o">~</span><span class="mi">0</span><span class="n">b11</span> <span class="o">//</span> <span class="err">按位取反</span>
</span><span class='line'><span class="n">let</span> <span class="ow">and</span><span class="p">:</span> <span class="n">UInt8</span> <span class="o">=</span> <span class="mh">0xF</span> <span class="o">&</span> <span class="mh">0xF0</span> <span class="o">//</span> <span class="err">按位与</span>
</span><span class='line'><span class="n">let</span> <span class="ow">or</span><span class="p">:</span> <span class="n">UInt8</span> <span class="o">=</span> <span class="mh">0xF</span> <span class="o">|</span> <span class="mh">0xF0</span> <span class="o">//</span> <span class="err">按位或</span>
</span><span class='line'><span class="n">let</span> <span class="n">diff</span><span class="p">:</span> <span class="n">UInt8</span> <span class="o">=</span> <span class="mh">0xF</span> <span class="o"><sup></span></sup> <span class="mh">0xF0</span> <span class="o">//</span> <span class="err">按位异或</span>
</span><span class='line'><span class="n">let</span> <span class="n">left</span><span class="p">:</span> <span class="n">UInt8</span> <span class="o">=</span> <span class="mh">0xFF</span> <span class="o"><<</span> <span class="mi">1</span> <span class="o">//</span> <span class="err">按位左移</span>
</span><span class='line'><span class="n">let</span> <span class="n">right</span><span class="p">:</span> <span class="n">UInt8</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">>></span> <span class="mi">1</span> <span class="o">//</span> <span class="err">按位右移</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>运算符函数。<br>
让已有的运算符也可以对自定义的类和结构进行运算,这称为运算符重载。<br>
@infix表示中置运算符,如a + b;<br>
@prefix表示前置运算符,如-a;<br>
@postfix表示后置运算符,如i++;<br>
@assignment表示组合赋值运算符,还需要把左参数设置成 inout,如a += 3;
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">struct</span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'> <span class="n">var</span> <span class="n">x</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="mf">0.0</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="nd">@infix</span> <span class="n">func</span> <span class="o">+</span> <span class="p">(</span><span class="n">left</span><span class="p">:</span> <span class="n">Point</span><span class="p">,</span> <span class="n">right</span><span class="p">:</span> <span class="n">Point</span><span class="p">)</span> <span class="o">-></span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="n">Point</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">left</span><span class="o">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">right</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="n">left</span><span class="o">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">right</span><span class="o">.</span><span class="n">y</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="nd">@prefix</span> <span class="n">func</span> <span class="o">-</span> <span class="p">(</span><span class="n">p</span><span class="p">:</span> <span class="n">Point</span><span class="p">)</span> <span class="o">-></span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="n">Point</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="o">-</span><span class="n">p</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="o">-</span><span class="n">p</span><span class="o">.</span><span class="n">y</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="nd">@assignment</span> <span class="n">func</span> <span class="o">+=</span> <span class="p">(</span><span class="n">inout</span> <span class="n">l</span><span class="p">:</span> <span class="n">Point</span><span class="p">,</span> <span class="n">r</span><span class="p">:</span> <span class="n">Point</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="n">l</span> <span class="o">=</span> <span class="n">l</span> <span class="o">+</span> <span class="n">r</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="nd">@prefix</span> <span class="nd">@assignment</span> <span class="n">func</span> <span class="o">++</span> <span class="p">(</span><span class="n">inout</span> <span class="n">p</span><span class="p">:</span> <span class="n">Point</span><span class="p">)</span> <span class="o">-></span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'> <span class="n">p</span> <span class="o">+=</span> <span class="n">Point</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="mf">1.0</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mf">1.0</span><span class="p">)</span>
</span><span class='line'> <span class="k">return</span> <span class="n">p</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="nd">@postfix</span> <span class="n">func</span> <span class="o">++</span> <span class="p">(</span><span class="n">inout</span> <span class="n">p</span><span class="p">:</span> <span class="n">Point</span><span class="p">)</span> <span class="o">-></span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'> <span class="n">var</span> <span class="n">ret</span> <span class="o">=</span> <span class="n">p</span>
</span><span class='line'> <span class="o">++</span><span class="n">p</span>
</span><span class='line'> <span class="k">return</span> <span class="n">ret</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>自定义运算符。<br>
自定义的运算符只能从<code>/ = - + * % < > ! & | ^ ~</code>中选择。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">operator</span> <span class="n">prefix</span> <span class="o"><+></span> <span class="p">{}</span> <span class="o">//</span> <span class="err">先声明为运算符</span>
</span><span class='line'><span class="nd">@prefix</span> <span class="nd">@assignment</span> <span class="n">func</span> <span class="o"><+></span> <span class="p">(</span><span class="n">inout</span> <span class="n">p</span><span class="p">:</span> <span class="n">Point</span><span class="p">)</span> <span class="o">-></span> <span class="n">Point</span> <span class="p">{</span>
</span><span class='line'> <span class="n">p</span> <span class="o">+=</span> <span class="n">p</span>
</span><span class='line'> <span class="k">return</span> <span class="n">p</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="n">var</span> <span class="n">p</span> <span class="o">=</span> <span class="n">Point</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mi">4</span><span class="p">)</span>
</span><span class='line'><span class="o"><+></span><span class="n">p</span>
</span><span class='line'>
</span><span class='line'><span class="o">//</span> <span class="err">自定义中置运算符可以定义优先级(默认为</span><span class="mi">100</span><span class="err">)和结合性(默认为</span><span class="n">none</span><span class="err">)</span>
</span><span class='line'><span class="n">operator</span> <span class="n">infix</span> <span class="o">+-</span> <span class="p">{</span> <span class="n">associativity</span> <span class="n">left</span> <span class="n">precedence</span> <span class="mi">140</span> <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
更完整的运算符的优先级和结合性参考<a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/doc/uid/TP40014097-CH32-XID_655">官方文档</a></p>
<h2 id="字符和字符串">字符和字符串</h2>
<p>字符串字面量可以包含一下特殊字符:</p>
<ol>
<li>转义特殊字符 <code>\0 (空字符)、\\(反斜线)、\t (水平制表符)、\n (换行符)、\r (回车符)、\" (双引号)、\' (单引号)</code>。</li>
<li>单字节 Unicode 标量,写成<code>\xnn</code>,其中 nn 为两位十六进制数。</li>
<li>双字节 Unicode 标量,写成<code>\unnnn</code>,其中 nnnn 为四位十六进制数。</li>
<li>四字节 Unicode 标量,写成<code>\Unnnnnnnn</code>,其中 nnnnnnnn 为八位十六进制数。</li>
</ol>
<p>空字符串定义,二者等价
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">var</span> <span class="n">empty1</span> <span class="o">=</span> <span class="s">""</span>
</span><span class='line'><span class="n">var</span> <span class="n">empty2</span> <span class="o">=</span> <span class="n">String</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>字符串可以通过“+”拼接,两个Character可以相加得到String。
字符串String可以作为字符Character的集合,可以对其用for-in操作,如 <code>for character in "Dog!???"</code>。</p>
<p>计算字符串中字符的数量,通过全局countElements函数实现。<br>
计算字符串的字节数,可以考虑 utf16count * 2 得到。</p>
<p>字符串比较。可以通过<code>==</code>判断两个字符串包含的字符是否完全相同,通过hasPrefix/hasSuffix判断前缀/后缀是否相等。</p>
<p>可以通过uppercaseString/lowercaseString获得大写/小写版本。<br>
可以通过utf8获得UTF-8单元集合。<br>
可以通过utf16获得UTF-16单元集合。<br>
可以通过unicodeScalars获得21位的标量值集合。</p>
<h2 id="集合类型">集合类型</h2>
<p>Swift提供了数组和字典两种集合类型。</p>
<h3 id="数组">数组</h3>
<p>数组是类型安全的,要求有明确的类型,其中包含的元素的类型必须统一。</p>
<p>数组的定义
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">var</span> <span class="n">arrSimple</span><span class="p">:</span> <span class="n">String</span><span class="p">[]</span> <span class="o">=</span> <span class="p">[</span><span class="s">"one"</span><span class="p">,</span> <span class="s">"two"</span><span class="p">]</span>
</span><span class='line'><span class="n">var</span> <span class="n">arrComp</span><span class="p">:</span> <span class="n">Array</span><span class="o"><</span><span class="n">String</span><span class="o">></span> <span class="o">=</span> <span class="p">[</span><span class="s">"one"</span><span class="p">,</span> <span class="s">"two"</span><span class="p">]</span>
</span><span class='line'><span class="n">var</span> <span class="n">arr</span> <span class="o">=</span> <span class="p">[</span><span class="s">"one"</span><span class="p">,</span> <span class="s">"two"</span><span class="p">]</span> <span class="o">//</span> <span class="err">依赖类型推断</span>
</span><span class='line'><span class="o">//</span> <span class="err">定义空数组</span>
</span><span class='line'><span class="n">var</span> <span class="n">emptySimple</span><span class="p">:</span> <span class="n">String</span><span class="p">[]</span> <span class="o">=</span> <span class="n">String</span><span class="p">[]</span> <span class="p">()</span>
</span><span class='line'><span class="n">var</span> <span class="n">emptyComp</span><span class="p">:</span> <span class="n">Array</span><span class="o"><</span><span class="n">String</span><span class="o">></span> <span class="o">=</span> <span class="n">Array</span><span class="o"><</span><span class="n">String</span><span class="o">></span><span class="p">()</span>
</span><span class='line'><span class="n">var</span> <span class="n">emptyNotOK</span> <span class="o">=</span> <span class="p">[]</span> <span class="o">//</span> <span class="err">未说明类型,后续无法使用</span>
</span><span class='line'><span class="n">emptySimple</span> <span class="o">=</span> <span class="p">[]</span> <span class="o">//</span> <span class="err">类型已知的情况下,可以用于变为空数组</span>
</span><span class='line'><span class="o">//</span> <span class="err">用重复的值初始化数组</span>
</span><span class='line'><span class="n">var</span> <span class="n">threeDoubles</span> <span class="o">=</span> <span class="n">Double</span><span class="p"><a href="http://erikge.com/span%3E%3Cspan%20class=%22n%22%3Ecount%3C/span%3E%3Cspan%20class=%22p%22%3E:%3C/span%3E%20%3Cspan%20class=%22mi%22%3E3%3C/span%3E%3Cspan%20class=%22p%22%3E,%3C/span%3E%20%3Cspan%20class=%22n%22%3ErepeatedValue%3C/span%3E%3Cspan%20class=%22p%22%3E:%3C/span%3E%3Cspan%20class=%22mf%22%3E0.0%3C/span%3E%3Cspan%20class=%22p%22"></a></span>
</span><span class='line'><span class="n">var</span> <span class="n">anotherThreeDoubles</span> <span class="o">=</span> <span class="n">Array</span><span class="p">(</span><span class="n">count</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="n">repeatedValue</span><span class="p">:</span> <span class="mf">2.5</span><span class="p">)</span> <span class="o">//</span> <span class="err">不指定类型,依赖类型推断</span>
</span><span class='line'><span class="o">//</span> <span class="n">copy</span><span class="err">创建</span>
</span><span class='line'><span class="n">var</span> <span class="n">arr_new</span> <span class="o">=</span> <span class="n">Array</span><span class="p">(</span><span class="n">arr_old</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>数组的使用
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">var</span> <span class="n">arr</span> <span class="o">=</span> <span class="n">String</span><span class="p"><a href=""></a></span>
</span><span class='line'><span class="n">arr</span><span class="o">.</span><span class="n">count</span> <span class="o">//</span> <span class="err">内部元素数量</span>
</span><span class='line'><span class="n">arr</span><span class="o">.</span><span class="n">isEmpty</span>
</span><span class='line'><span class="o">//</span> <span class="err">最后添加元素</span>
</span><span class='line'><span class="n">arr</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">"newValue"</span><span class="p">)</span>
</span><span class='line'><span class="n">arr</span> <span class="o">+=</span> <span class="p">[</span><span class="s">"newValue1"</span><span class="p">,</span> <span class="s">"newValue2"</span><span class="p">]</span>
</span><span class='line'><span class="o">//</span> <span class="err">将数组中的一段替换为新值,被替换的部分的长度和新值的长度可以不一致</span>
</span><span class='line'><span class="n">arr</span><span class="p">[</span><span class="mf">1.</span><span class="o">..</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="s">"one"</span><span class="p">,</span> <span class="s">"two"</span><span class="p">,</span> <span class="s">"three"</span><span class="p">,</span> <span class="s">"four"</span><span class="p">]</span>
</span><span class='line'><span class="o">//</span> <span class="err">添加、删除</span>
</span><span class='line'><span class="n">arr</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="s">"insertValue"</span><span class="p">,</span> <span class="n">atIndex</span><span class="p">:</span> <span class="mi">0</span><span class="p">)</span>
</span><span class='line'><span class="n">arr</span><span class="o">.</span><span class="n">removeAtIndex</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</span><span class='line'><span class="n">arr</span><span class="o">.</span><span class="n">removeLast</span><span class="p">()</span>
</span><span class='line'><span class="o">//</span> <span class="err">带数组的索引遍历</span>
</span><span class='line'><span class="k">for</span> <span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">shoppingList</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'><span class="n">println</span><span class="p">(</span><span class="s">"Item (index + 1): (value)"</span><span class="p">)</span>
</span><span class='line'><span class="o">//</span> <span class="err">数组可以相加来合并</span>
</span><span class='line'><span class="n">var</span> <span class="n">arr</span> <span class="o">=</span> <span class="n">arr1</span> <span class="o">+</span> <span class="n">arr2</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>当数组分配给常量时,数组的长度不能改变,但其中的值还可以改变。</p>
<h3 id="字典">字典</h3>
<p>Swift 的字典使用 Dictionary<KeyType, ValueType>定义,其中KeyType要求是可哈希的。</p>
<p>字典的定义
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">var</span> <span class="n">airports</span><span class="p">:</span> <span class="n">Dictionary</span><span class="o"><</span><span class="n">String</span><span class="p">,</span> <span class="n">String</span><span class="o">></span> <span class="o">=</span> <span class="p">[</span><span class="s">"TYO"</span><span class="p">:</span> <span class="s">"Tokyo"</span><span class="p">,</span> <span class="s">"DUB"</span><span class="p">:</span> <span class="s">"Dublin"</span><span class="p">]</span>
</span><span class='line'><span class="n">var</span> <span class="n">airports</span> <span class="o">=</span> <span class="p">[</span><span class="s">"TYO"</span><span class="p">:</span> <span class="s">"Tokyo"</span><span class="p">,</span> <span class="s">"DUB"</span><span class="p">:</span> <span class="s">"Dublin"</span><span class="p">]</span> <span class="o">//</span> <span class="err">依赖类型推断</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>字典的使用
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="o">//</span> <span class="err">添加</span>
</span><span class='line'><span class="n">airports</span><span class="p">[</span><span class="s">"LHR"</span><span class="p">]</span> <span class="o">=</span> <span class="s">"London"</span>
</span><span class='line'><span class="o">//</span> <span class="err">更新</span>
</span><span class='line'><span class="n">airports</span><span class="p">[</span><span class="s">"LHR"</span><span class="p">]</span> <span class="o">=</span> <span class="s">"London Heathrow"</span>
</span><span class='line'><span class="n">airports</span><span class="o">.</span><span class="n">updateValue</span><span class="p">(</span><span class="s">"London Heathrow"</span><span class="p">,</span> <span class="n">forKey</span><span class="p">:</span><span class="s">"LHR"</span><span class="p">)</span>
</span><span class='line'><span class="o">//</span> <span class="err">遍历</span>
</span><span class='line'><span class="k">for</span> <span class="p">(</span><span class="n">airportCode</span><span class="p">,</span> <span class="n">airportName</span><span class="p">)</span> <span class="ow">in</span> <span class="n">airports</span> <span class="p">{</span>
</span><span class='line'> <span class="n">println</span><span class="p">(</span><span class="s">"(airportCode): (airportName)"</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>当字典分配给常量时,大小和其中的键值对都不能更改。</p>
<h2 id="值类型和引用类型">值类型和引用类型</h2>
<p>Swift中的类型可以分为值类型和引用类型。<br>
值类型赋值给变量、常量,或传递给函数参数,或函数返回值时,得到的是新创建的一份拷贝。这样两个变量的后续操作相互独立,不相互影响。<br>
引用类型在代码中传递时,得到的是同一个实例。两个变量的后续操作实际是对同一实例的操作。<br>
引用类似C中的指针、Java中的类对象引用。Swift中也是没有指针、地址等概念的。</p>
<p><strong>值类型:</strong></p>
<ul>
<li>所有的基本类型。整数(Integer)、浮点数(floating-point)、布尔值(Booleans)、字符串(string)、数组(array)和字典(dictionaries)。并且都是以结构体的形式在后台实现。</li>
<li>结构体、枚举。其中包含的任何值类型,在代码中传递时都会被复制。</li>
</ul>
<p><strong>引用类型:</strong></p>
<ul>
<li>类</li>
<li>闭包。闭包包括函数。</li>
</ul>
<p>恒等运算符(恒等<code>===</code>、不恒等<code>!==</code>),判断两个变量、常量是否引用同一个实例的方法。</p>
<p>在实际开发中,并没有必要因为值拷贝的原因减少赋值等传递。因为在实际编译时,编译器会保证复制只发生在绝对必要的情况下以提高性能</p>
<p>集合类型的传递和拷贝行为略有些复杂。集合类型在传递时,先不做拷贝,只有当值发生变化时才执行拷贝。字典在其中的键-值对改变或size改变时,都认为是发生变化,触发拷贝;但数组在修改其中元素时不认为是发生变化,只有在长度改变时才认为是发生变化,才触发拷贝。
数组长度改变的情况包括附加(appending),插入(inserting),删除(removing)或者使用范围下标(ranged subscript)去替换这一范围内的元素。</p>
<p>集合类型在拷贝时执行的都是浅拷贝。当其中的元素时引用类型时,拷贝的是引用。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">var</span> <span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">],</span> <span class="n">b</span> <span class="o">=</span> <span class="n">a</span>
</span><span class='line'><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">10</span>
</span><span class='line'><span class="n">a</span> <span class="o">==</span> <span class="n">b</span> <span class="o">//</span> <span class="n">true</span><span class="err">,没</span><span class="n">copy</span><span class="err">,</span><span class="n">a</span><span class="err">修改不认为是变化</span>
</span><span class='line'><span class="n">a</span> <span class="o">===</span> <span class="n">b</span> <span class="o">//</span> <span class="n">false</span><span class="err">,值类型,返回</span><span class="n">false</span><span class="err">符合语法</span>
</span><span class='line'><span class="n">a</span><span class="p">[</span><span class="mf">1.</span><span class="o">..</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">]</span>
</span><span class='line'><span class="n">a</span> <span class="o">==</span> <span class="n">b</span> <span class="o">//</span> <span class="n">false</span><span class="err">,发生</span><span class="n">copy</span><span class="err">,</span><span class="n">a</span><span class="err">变化了</span>
</span></code></pre></td></tr></table></div></figure>
触发copy的方法
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">var</span> <span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">],</span> <span class="n">b</span> <span class="o">=</span> <span class="n">a</span>
</span><span class='line'><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">10</span>
</span><span class='line'><span class="n">b</span><span class="o">.</span><span class="n">unshare</span><span class="p">()</span> <span class="o">//</span> <span class="err">触发</span><span class="n">b</span><span class="err">的</span><span class="n">copy</span>
</span><span class='line'><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">11</span> <span class="o">//</span> <span class="n">a</span><span class="p">[</span><span class="mi">10</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">b</span><span class="p">[</span><span class="mi">10</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span>
</span><span class='line'><span class="o">//</span> <span class="ow">or</span>
</span><span class='line'><span class="n">var</span> <span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
</span><span class='line'><span class="n">var</span> <span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
</span><span class='line'><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">10</span>
</span><span class='line'><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">11</span> <span class="o">//</span> <span class="n">a</span><span class="p">[</span><span class="mi">10</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span>
</span></code></pre></td></tr></table></div></figure></p>
<h2 id="函数">函数</h2>
<p>多返回值。<br>
函数可以返回多个值,以元组的形式实现。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">func</span> <span class="n">getPoint</span><span class="p">()</span> <span class="o">-></span> <span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">Int</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="n">Int</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="n">var</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">8</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">7</span>
</span><span class='line'> <span class="k">return</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="n">var</span> <span class="n">ret</span> <span class="o">=</span> <span class="n">getPoint</span><span class="p">()</span>
</span><span class='line'><span class="n">ret</span><span class="o">.</span><span class="n">x</span>
</span><span class='line'><span class="n">ret</span><span class="o">.</span><span class="n">y</span>
</span><span class='line'><span class="n">func</span> <span class="n">getInfo</span><span class="p">()</span> <span class="o">-></span> <span class="p">(</span><span class="n">Int</span><span class="p">,</span> <span class="n">String</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="p">(</span><span class="mi">9</span><span class="p">,</span> <span class="s">"Not Found"</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="n">var</span> <span class="n">info</span> <span class="o">=</span> <span class="n">getInfo</span><span class="p">()</span>
</span><span class='line'><span class="n">info</span><span class="o">.</span><span class="mi">0</span>
</span><span class='line'><span class="n">info</span><span class="o">.</span><span class="mi">1</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>外部形参名。<br>
函数形参名分为本地形参名和外部形参名。本地形参名只在函数内部有效,外部形参名用于外部调用时声明。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">func</span> <span class="n">join</span><span class="p">(</span><span class="n">string</span> <span class="n">s1</span><span class="p">:</span> <span class="n">String</span><span class="p">,</span> <span class="n">toString</span> <span class="n">s2</span><span class="p">:</span> <span class="n">String</span><span class="p">,</span> <span class="n">withJoiner</span> <span class="n">joiner</span><span class="p">:</span> <span class="n">String</span><span class="p">)</span> <span class="o">-></span> <span class="n">String</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="n">s1</span> <span class="o">+</span> <span class="n">joiner</span> <span class="o">+</span> <span class="n">s2</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="o">//</span> <span class="n">usage</span>
</span><span class='line'><span class="n">join</span><span class="p">(</span><span class="n">string</span><span class="p">:</span> <span class="s">"Hello"</span><span class="p">,</span> <span class="n">toString</span><span class="p">:</span> <span class="s">"world"</span><span class="p">,</span> <span class="n">withJoiner</span><span class="p">:</span> <span class="s">", "</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
外部形参和本地形参同名。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">func</span> <span class="n">join</span><span class="p">(</span><span class="c">#string: String, #toString: String, #withJoiner: String) -> String {</span>
</span><span class='line'> <span class="k">return</span> <span class="n">string</span> <span class="o">+</span> <span class="n">withJoiner</span> <span class="o">+</span> <span class="n">toString</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="n">join</span><span class="p">(</span><span class="n">string</span><span class="p">:</span> <span class="s">"Hello"</span><span class="p">,</span> <span class="n">toString</span><span class="p">:</span> <span class="s">"world"</span><span class="p">,</span> <span class="n">withJoiner</span><span class="p">:</span> <span class="s">", "</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>默认值。<br>
函数形参可以带有默认值,虽然默认值形参可以在任何位置,但是建议放在形参列表的末尾。<br>
Swift为带默认值的形参自动提供了外部形参名,可以通过"_“来关闭这种行为
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">func</span> <span class="n">join</span><span class="p">(</span><span class="n">s1</span><span class="p">:</span> <span class="n">String</span><span class="p">,</span> <span class="n">s2</span><span class="p">:</span> <span class="n">String</span> <span class="o">=</span> <span class="s">"world"</span><span class="p">,</span> <span class="n">jo</span><span class="p">:</span> <span class="n">String</span><span class="p">)</span> <span class="o">-></span> <span class="n">String</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="n">s1</span> <span class="o">+</span> <span class="n">jo</span> <span class="o">+</span> <span class="n">s2</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="n">join</span><span class="p">(</span><span class="s">"Hello"</span><span class="p">,</span> <span class="s">", "</span><span class="p">)</span> <span class="o">//</span> <span class="err">输出</span> <span class="s">"Hello, world"</span>
</span><span class='line'><span class="n">join</span><span class="p">(</span><span class="s">"Hello"</span><span class="p">,</span> <span class="n">s2</span><span class="p">:</span> <span class="s">"Amy"</span><span class="p">,</span> <span class="s">", "</span><span class="p">)</span> <span class="o">//</span> <span class="err">不使用默认值</span>
</span><span class='line'>
</span><span class='line'><span class="n">func</span> <span class="n">join2</span><span class="p">(</span><span class="n">s1</span><span class="p">:</span> <span class="n">String</span><span class="p">,</span> <span class="n">_</span> <span class="n">s2</span><span class="p">:</span> <span class="n">String</span> <span class="o">=</span> <span class="s">"world"</span><span class="p">,</span> <span class="n">jo</span><span class="p">:</span> <span class="n">String</span><span class="p">)</span> <span class="o">-></span> <span class="n">String</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="n">s1</span> <span class="o">+</span> <span class="n">jo</span> <span class="o">+</span> <span class="n">s2</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="n">join2</span><span class="p">(</span><span class="s">"Hello"</span><span class="p">,</span> <span class="s">"Foo"</span><span class="p">,</span> <span class="s">", "</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>可变形参。<br>
传递至可变形参的值在函数主体内是以适当类型的数组存在的。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">func</span> <span class="n">arithmeticMean</span><span class="p">(</span><span class="n">numbers</span><span class="p">:</span> <span class="n">Double</span><span class="o">...</span><span class="p">)</span> <span class="o">-></span> <span class="n">Double</span> <span class="p">{</span>
</span><span class='line'> <span class="k">for</span> <span class="n">number</span> <span class="ow">in</span> <span class="n">numbers</span> <span class="p">{</span>
</span><span class='line'> <span class="o">//</span> <span class="n">todo</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>变量形参。<br>
函数的形参默认是常量。试图在函数体内改变函数形参的值会引发一个编译时错误。
可以通过使用变量形参,在函数内得到一个有形参值的变量副本。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">func</span> <span class="n">add</span><span class="p">(</span><span class="n">var</span> <span class="n">a</span><span class="p">:</span> <span class="n">Int</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span> <span class="n">Int</span><span class="p">)</span> <span class="o">-></span> <span class="n">Int</span><span class="p">{</span>
</span><span class='line'> <span class="n">a</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>
</span><span class='line'> <span class="k">return</span> <span class="n">a</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>In-Out形参。<br>
只能传递一个变量作为 in-out 形参对应的实参,变量前加&号。
不能传递一个常量或者字面量作为实参,因为常量和字面量不能被修改。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">func</span> <span class="n">swap</span><span class="p">(</span><span class="n">inout</span> <span class="n">a</span><span class="p">:</span><span class="n">Int</span><span class="p">,</span> <span class="n">inout</span> <span class="n">b</span><span class="p">:</span><span class="n">Int</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="n">let</span> <span class="n">temp</span> <span class="o">=</span> <span class="n">a</span>
</span><span class='line'> <span class="n">a</span> <span class="o">=</span> <span class="n">b</span>
</span><span class='line'> <span class="n">b</span> <span class="o">=</span> <span class="n">temp</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="o">//</span> <span class="n">usage</span>
</span><span class='line'><span class="n">var</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">5</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">9</span>
</span><span class='line'><span class="n">swap</span><span class="p">(</span><span class="o">&</span><span class="n">x</span><span class="p">,</span> <span class="o">&</span><span class="n">y</span><span class="p">)</span>
</span><span class='line'><span class="n">x</span> <span class="o">//</span> <span class="mi">9</span>
</span><span class='line'><span class="n">y</span> <span class="o">//</span> <span class="mi">5</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>嵌套函数。<br>
除了在全局作用域中定义的全局函数外,还可以在函数体内部定义嵌套函数。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">func</span> <span class="n">chooseStepFunction</span><span class="p">(</span><span class="n">backwards</span><span class="p">:</span> <span class="n">Bool</span><span class="p">)</span> <span class="o">-></span> <span class="p">(</span><span class="n">Int</span><span class="p">)</span> <span class="o">-></span> <span class="n">Int</span> <span class="p">{</span>
</span><span class='line'> <span class="n">func</span> <span class="n">stepForward</span><span class="p">(</span><span class="nb">input</span><span class="p">:</span> <span class="n">Int</span><span class="p">)</span> <span class="o">-></span> <span class="n">Int</span> <span class="p">{</span> <span class="k">return</span> <span class="nb">input</span> <span class="o">+</span> <span class="mi">1</span> <span class="p">}</span>
</span><span class='line'> <span class="n">func</span> <span class="n">stepBackward</span><span class="p">(</span><span class="nb">input</span><span class="p">:</span> <span class="n">Int</span><span class="p">)</span> <span class="o">-></span> <span class="n">Int</span> <span class="p">{</span> <span class="k">return</span> <span class="nb">input</span> <span class="o">-</span> <span class="mi">1</span> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'> <span class="k">return</span> <span class="n">backwards</span> <span class="err">?</span> <span class="n">stepBackward</span> <span class="p">:</span> <span class="n">stepForward</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></p>
<h2 id="类和结构体">类和结构体</h2>
<p>类和结构体有很多共同点:</p>
<ul>
<li>定义属性用于储存值</li>
<li>定义方法用于提供功能</li>
<li>定义下标用于通过下标语法访问值</li>
<li>定义初始化器用于生成初始化值</li>
<li>通过扩展以增加默认实现的功能</li>
<li>符合协议以对某类提供标准功能</li>
</ul>
<p>与结构体相比,类还有如下的附加功能:</p>
<ul>
<li>继承允许一个类继承另一个类的特征</li>
<li>类型转换允许在运行时检查和解释一个类实例的类型</li>
<li>取消初始化器允许一个类实例释放任何其所被分配的资源</li>
<li>引用计数允许对一个类的多次引用</li>
</ul>
<p>定义:
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">class</span> <span class="nc">SomeClass</span> <span class="p">{</span>
</span><span class='line'> <span class="o">//</span> <span class="k">class</span> <span class="nc">definition</span> <span class="n">goes</span> <span class="n">here</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="n">struct</span> <span class="n">SomeStructure</span> <span class="p">{</span>
</span><span class='line'> <span class="o">//</span> <span class="n">structure</span> <span class="n">definition</span> <span class="n">goes</span> <span class="n">here</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></p>
<h3 id="属性">属性</h3>
<p>属性部分包含:</p>
<ol>
<li>存储属性。存储常量、变量,可用于类和结构体</li>
<li>计算属性。计算值,可用于类、结构体和枚举</li>
<li>属性监视器。监控属性值的变化</li>
</ol>
<p>存储属性。<br>
@lazy标示的为延迟存储属性,创建时为nil,在第一次被调用时才初始化。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">class</span> <span class="nc">Lazy</span> <span class="p">{</span>
</span><span class='line'> <span class="n">let</span> <span class="n">left</span><span class="p">:</span> <span class="n">Int</span> <span class="o">=</span> <span class="mi">5</span>
</span><span class='line'> <span class="nd">@lazy</span> <span class="n">var</span> <span class="n">top</span><span class="p">:</span> <span class="n">Int</span> <span class="o">=</span> <span class="mi">3</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>计算属性。<br>
计算属性不直接存储值,提供一个get来获取值,一个可选的set来设置值。只实现get,不实现set时,为只读属性。计算属性只能通过var来定义。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">struct</span> <span class="n">Range</span> <span class="p">{</span>
</span><span class='line'> <span class="n">var</span> <span class="n">normal</span><span class="p">:</span> <span class="n">String</span> <span class="p">{</span>
</span><span class='line'> <span class="n">get</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="s">"Getter"</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="nb">set</span> <span class="p">(</span><span class="n">new_str</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="n">println</span><span class="p">(</span><span class="n">new_str</span><span class="p">)</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="n">var</span> <span class="n">quick</span><span class="p">:</span> <span class="n">Double</span> <span class="p">{</span>
</span><span class='line'> <span class="n">get</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="mf">1.0</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="nb">set</span> <span class="p">{</span> <span class="o">//</span> <span class="err">默认参数名为</span> <span class="n">newValue</span>
</span><span class='line'> <span class="n">println</span><span class="p">(</span><span class="n">newValue</span><span class="p">)</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="n">var</span> <span class="n">quickReadOnly</span><span class="p">:</span> <span class="n">Int</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="mi">1</span> <span class="o">+</span> <span class="mi">1</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="n">var</span> <span class="n">ran</span> <span class="o">=</span> <span class="n">Range</span><span class="p">()</span>
</span><span class='line'><span class="n">ran</span><span class="o">.</span><span class="n">normal</span>
</span><span class='line'><span class="n">ran</span><span class="o">.</span><span class="n">normal</span> <span class="o">=</span> <span class="s">"aabbcc"</span>
</span><span class='line'><span class="n">ran</span><span class="o">.</span><span class="n">quickReadOnly</span>
</span></code></pre></td></tr></table></div></figure></p>
<p>属性监视器。<br>
可以为除了延迟存储属性之外的其他存储属性添加属性监视器,也可以通过重载属性的方式为继承的属性(包括存储属性和计算属性)添加属性监视器。<br>
willSet 在设置新的值之前调用,将新的值作为参数传入,默认名称为newValue。didSet 在新的值被设置之后立即调用,将旧的属性值作为参数传入,默认名称为oldValue。<br>
willSet 和 didSet 监视器在属性初始化过程中不会被调用,他们只会当属性的值在初始化之外的地方被设置时被调用。</p>
<p>计算属性和存储型属性监视器所描述的模式也可以用于全局变量和局部变量,即可定义计算型变量和为存储型变量定义监视器。</p>
<p>类型属性。<br>
上述的属性在实例之间相互独立,属于实例属性。也可以为类型定义类型属性,不管有多少实例,这些属性都只有一份。<br>
对于值类型(指结构体和枚举)可以定义存储型和计算型类型属性,对于类(class)则只能 定义计算型类型属性。
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">struct</span> <span class="n">SomeStruct</span> <span class="p">{</span>
</span><span class='line'> <span class="n">static</span> <span class="n">let</span> <span class="nb">property</span> <span class="o">=</span> <span class="s">"structure"</span>
</span><span class='line'> <span class="n">static</span> <span class="n">var</span> <span class="nb">type</span><span class="p">:</span> <span class="n">Int</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="mi">0</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="n">enum</span> <span class="n">SomeEnum</span> <span class="p">{</span>
</span><span class='line'> <span class="n">static</span> <span class="n">let</span> <span class="nb">property</span> <span class="o">=</span> <span class="s">"enumeration"</span>
</span><span class='line'> <span class="n">static</span> <span class="n">var</span> <span class="nb">type</span><span class="p">:</span> <span class="n">Int</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="mi">1</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="k">class</span> <span class="nc">SomeClass</span> <span class="p">{</span>
</span><span class='line'> <span class="k">class</span> <span class="nc">var</span> <span class="nb">type</span><span class="p">:</span> <span class="n">Int</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span> <span class="mi">2</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="o">//</span> <span class="n">usage</span>
</span><span class='line'><span class="n">SomeStruct</span><span class="o">.</span><span class="n">type</span>
</span></code></pre></td></tr></table></div></figure></p>
<h3 id="方法">方法</h3>
<p>类、结构体、枚举都可以定义实例方法或类型方法。方法自动为第二个参数和后续所有参数提供同名外部参数名称,可以自己指定外部参数名,或通过”_“关闭默认行为。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">class</span> <span class="nc">Counter</span> <span class="p">{</span>
</span><span class='line'> <span class="n">var</span> <span class="n">value</span> <span class="o">=</span> <span class="mi">1</span>
</span><span class='line'>
</span><span class='line'> <span class="n">func</span> <span class="n">increase</span><span class="p">(</span><span class="n">amout</span><span class="p">:</span> <span class="n">Int</span><span class="p">,</span> <span class="n">times</span> <span class="p">:</span><span class="n">Int</span><span class="p">)</span> <span class="o">-></span> <span class="n">Int</span><span class="p">{</span>
</span><span class='line'> <span class="n">value</span> <span class="o">+=</span> <span class="n">amout</span> <span class="o">*</span> <span class="n">times</span>
</span><span class='line'> <span class="k">return</span> <span class="n">value</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="n">func</span> <span class="n">increase</span><span class="p">(</span><span class="n">amout</span><span class="p">:</span> <span class="n">Int</span><span class="p">,</span> <span class="n">numberOfTimes</span> <span class="n">times</span> <span class="p">:</span><span class="n">Int</span><span class="p">)</span> <span class="o">-></span> <span class="n">Int</span><span class="p">{</span>
</span><span class='line'> <span class="n">value</span> <span class="o">+=</span> <span class="n">amout</span> <span class="o">*</span> <span class="n">times</span> <span class="o">+</span> <span class="mi">1</span>
</span><span class='line'> <span class="k">return</span> <span class="n">value</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="n">func</span> <span class="n">increase</span><span class="p">(</span><span class="n">amout</span><span class="p">:</span> <span class="n">Int</span><span class="p">,</span> <span class="n">_</span> <span class="n">times</span> <span class="p">:</span><span class="n">Int</span><span class="p">)</span> <span class="o">-></span> <span class="n">Int</span><span class="p">{</span>
</span><span class='line'> <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">+=</span> <span class="n">amout</span> <span class="o">*</span> <span class="n">times</span> <span class="o">+</span> <span class="mi">2</span>