-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlocal-search.xml
1283 lines (617 loc) · 900 KB
/
local-search.xml
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"?>
<search>
<entry>
<title>算法题T4</title>
<link href="/2021/12/05/%E7%AE%97%E6%B3%95%E9%A2%98T4/"/>
<url>/2021/12/05/%E7%AE%97%E6%B3%95%E9%A2%98T4/</url>
<content type="html"><![CDATA[<blockquote><p>从n个正整数中找出满足如下条件的组合数量,满足条件:1个数或者2个数之和,大于等于n,每个数最多组合一次</p><p>例如:输入[3, 7, 1, 5, 9],n = 8,输出:3</p></blockquote><figure class="highlight stata"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><code class="hljs stata"><span class="hljs-comment">/*</span><br><span class="hljs-comment"> </span><br><span class="hljs-comment"> */</span><br>let <span class="hljs-keyword">input</span> = [3, 7, 1, 5, 9]<br><span class="hljs-keyword">print</span>(<span class="hljs-string">"输入:"</span>, <span class="hljs-keyword">input</span>)<br>let <span class="hljs-keyword">n</span> = 8<br><span class="hljs-keyword">print</span>(<span class="hljs-string">"输入:"</span>, <span class="hljs-keyword">n</span>)<br><span class="hljs-comment">// 先从小到大排序</span><br><span class="hljs-keyword">var</span> sInput = <span class="hljs-keyword">input</span>.sorted { e1, e2 <span class="hljs-keyword">in</span><br> <span class="hljs-keyword">return</span> e1 > e2 ? false : true<br>}<br><span class="hljs-keyword">var</span> <span class="hljs-keyword">count</span> = 0<br><span class="hljs-comment">// 先筛选单个数字满足条件的</span><br><span class="hljs-keyword">var</span> nInput: [Int] = []<br><span class="hljs-keyword">for</span> <span class="hljs-keyword">e</span> <span class="hljs-keyword">in</span> sInput {<br> <span class="hljs-keyword">if</span> <span class="hljs-keyword">e</span> >= <span class="hljs-keyword">n</span> {<br> <span class="hljs-keyword">count</span> += 1<br> } <span class="hljs-keyword">else</span> {<br> nInput.<span class="hljs-keyword">append</span>(<span class="hljs-keyword">e</span>)<br> }<br>}<br>sInput = nInput;<br><span class="hljs-keyword">while</span> sInput.<span class="hljs-keyword">count</span> >= 2 {<br> <span class="hljs-comment">// 存储需要剔除的元素索引值</span><br> <span class="hljs-keyword">var</span> <span class="hljs-keyword">cl</span>: [Int] = []<br> <span class="hljs-comment">// 使用最大值+最小值进行判断</span><br> let last = sInput[sInput.<span class="hljs-keyword">count</span> - 1]<br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> 0 ..< (sInput.<span class="hljs-keyword">count</span> - 1) {<br> let <span class="hljs-keyword">e</span> = sInput[i];<br> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">e</span> + last) >= <span class="hljs-keyword">n</span> {<br> <span class="hljs-keyword">count</span> += 1<br> <span class="hljs-keyword">cl</span>.<span class="hljs-keyword">append</span>(i);<br> <span class="hljs-keyword">cl</span>.<span class="hljs-keyword">append</span>(sInput.<span class="hljs-keyword">count</span> - 1);<br> <span class="hljs-keyword">break</span><br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">cl</span>.<span class="hljs-keyword">append</span>(i);<br> }<br> }<br> <span class="hljs-keyword">for</span> <span class="hljs-keyword">e</span> <span class="hljs-keyword">in</span> <span class="hljs-keyword">cl</span>.reversed() {<br> sInput.remove(at: <span class="hljs-keyword">e</span>)<br> }<br>}<br><span class="hljs-keyword">print</span>(<span class="hljs-string">"输出:"</span>, <span class="hljs-keyword">count</span>)<br></code></pre></td></tr></table></figure><figure class="highlight accesslog"><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><code class="hljs accesslog">输入: <span class="hljs-string">[3, 7, 1, 5, 9]</span><br>输入: <span class="hljs-number">8</span><br>输出: <span class="hljs-number">3</span><br></code></pre></td></tr></table></figure>]]></content>
<categories>
<category>算法</category>
</categories>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>算法题T3</title>
<link href="/2021/11/02/%E7%AE%97%E6%B3%95%E9%A2%98T3/"/>
<url>/2021/11/02/%E7%AE%97%E6%B3%95%E9%A2%98T3/</url>
<content type="html"><![CDATA[<blockquote><p>输入一个整型数组,找出其中出现次数超过一半以上的元素,输出该元素,例如:输入[1,5,9,5,5,4,8,5,5],输出:5</p></blockquote><figure class="highlight nix"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><code class="hljs nix"><span class="hljs-comment">/*</span><br><span class="hljs-comment"> 遍历数组,保存两个值,一个是数组中的数组,一个是次数</span><br><span class="hljs-comment"> 当遍历下一个数字时,如果下一个数字和当前保存的数字相同,则次数加1,如果不同则次数减1,</span><br><span class="hljs-comment"> 如果次数为0,则需要保存下一个数字,并把次数设为1</span><br><span class="hljs-comment"> 由于要找的数字出现的次数比其他所有数字出现的次数之和还要多,所以要找的数字肯定是最后一次把次数设为1的那个数字</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-keyword">let</span> input: [Int] = [<span class="hljs-number">1</span>, <span class="hljs-number">5</span>, <span class="hljs-number">9</span>, <span class="hljs-number">5</span>, <span class="hljs-number">5</span>, <span class="hljs-number">4</span>, <span class="hljs-number">8</span>, <span class="hljs-number">5</span>, <span class="hljs-number">5</span>];<br>print(<span class="hljs-string">"输入:"</span>, input);<br><br>var n: Int!<br>var <span class="hljs-attr">c</span> = <span class="hljs-number">0</span><br><br>for i <span class="hljs-keyword">in</span> <span class="hljs-number">0</span> ..< input.count {<br> <span class="hljs-keyword">let</span> <span class="hljs-attr">e</span> = input[i];<br> <span class="hljs-keyword">if</span> <span class="hljs-attr">i</span> == <span class="hljs-number">0</span> {<br> <span class="hljs-attr">n</span> = e<br> <span class="hljs-attr">c</span> = <span class="hljs-number">1</span><br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">if</span> <span class="hljs-attr">n</span> == e {<br> c += <span class="hljs-number">1</span><br> } <span class="hljs-keyword">else</span> {<br> c <span class="hljs-attr">-=</span> <span class="hljs-number">1</span><br> <span class="hljs-keyword">if</span> <span class="hljs-attr">c</span> == <span class="hljs-number">0</span> {<br> <span class="hljs-attr">n</span> = e<br> <span class="hljs-attr">c</span> = <span class="hljs-number">1</span><br> }<br> }<br> }<br>}<br>print(<span class="hljs-string">"输出:"</span> + String(n));<br></code></pre></td></tr></table></figure><figure class="highlight accesslog"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs accesslog">输入: <span class="hljs-string">[1, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 4, 8, 5, 5]</span><br>输出:<span class="hljs-number">9</span><br></code></pre></td></tr></table></figure>]]></content>
<categories>
<category>算法</category>
</categories>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>算法题T2</title>
<link href="/2021/11/02/%E7%AE%97%E6%B3%95%E9%A2%98T2/"/>
<url>/2021/11/02/%E7%AE%97%E6%B3%95%E9%A2%98T2/</url>
<content type="html"><![CDATA[<blockquote><p> 绘制机器的绘笔初始位置在原点(0,0),机器启动后其绘图笔按下面规则绘制直线:<br>1) 尝试沿着横向正坐标轴绘制直线,直到给定的终点E。<br>2) 期间可以通过指令在纵坐标轴方向进行偏移,并同时绘制直线,偏移后按规则1绘制直线;指令的X offsetY,表示在横坐标轴X沿纵坐标方向偏移,offsetY为正数表示正向偏移,为负数表示负向偏移。<br>给定了横坐标终点值E,以及若干条绘制指令,请计算绘制的直线和横坐标轴以及X=E的直线组成图形的面积。</p></blockquote><figure class="highlight nix"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><code class="hljs nix"><span class="hljs-keyword">let</span> <span class="hljs-attr">E</span> = <span class="hljs-number">10</span><br><span class="hljs-keyword">let</span> C: [[Int:Int]] = [<br> [<span class="hljs-number">1</span> : <span class="hljs-number">1</span>],<br> [<span class="hljs-number">2</span> : <span class="hljs-number">1</span>],<br> [<span class="hljs-number">3</span> : <span class="hljs-number">1</span>],<br> [<span class="hljs-number">4</span> : -<span class="hljs-number">4</span>],<br> [<span class="hljs-number">5</span> : <span class="hljs-number">2</span>],<br>];<br><br>print(<span class="hljs-string">"输入终点:"</span> + String(E))<br><br>var <span class="hljs-attr">s</span> = <span class="hljs-number">0</span><br>var <span class="hljs-attr">offsetY</span> = <span class="hljs-number">0</span><br>for i <span class="hljs-keyword">in</span> <span class="hljs-number">0</span> ... C.count {<br> <span class="hljs-keyword">if</span> i < C.count {<br> <span class="hljs-keyword">let</span> <span class="hljs-attr">c</span> = C[i]<br> var <span class="hljs-attr">offsetX</span> = <span class="hljs-number">0</span><br> <span class="hljs-keyword">if</span> <span class="hljs-attr">i</span> == <span class="hljs-number">0</span> {<br> <span class="hljs-attr">offsetX</span> = c.keys.first!<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">let</span> <span class="hljs-attr">lc</span> = C[i - <span class="hljs-number">1</span>];<br> <span class="hljs-attr">offsetX</span> = c.keys.first! - lc.keys.first!<br> }<br> var <span class="hljs-attr">y</span> = <span class="hljs-number">0</span><br> <span class="hljs-keyword">if</span> offsetY < <span class="hljs-number">0</span> {<br> <span class="hljs-attr">y</span> = offsetY * -<span class="hljs-number">1</span><br> } <span class="hljs-keyword">else</span> {<br> y += offsetY<br> }<br> s += (offsetX * y)<br> offsetY += c.values.first!<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">let</span> <span class="hljs-attr">lc</span> = C[i - <span class="hljs-number">1</span>];<br> <span class="hljs-keyword">let</span><br> <span class="hljs-attr">offsetX</span> = E - lc.keys.first!<br> var <span class="hljs-attr">y</span> = <span class="hljs-number">0</span><br> <span class="hljs-keyword">if</span> offsetY < <span class="hljs-number">0</span> {<br> <span class="hljs-attr">y</span> = offsetY * -<span class="hljs-number">1</span><br> } <span class="hljs-keyword">else</span> {<br> y += offsetY<br> }<br> s += (offsetX * y)<br> }<br>}<br><br>print(<span class="hljs-string">"输出:"</span> + String(s));<br></code></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs plain">输入终点:10<br>输出:12<br></code></pre></td></tr></table></figure>]]></content>
<categories>
<category>算法</category>
</categories>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>算法题T1</title>
<link href="/2021/10/31/%E7%AE%97%E6%B3%95%E9%A2%98T1/"/>
<url>/2021/10/31/%E7%AE%97%E6%B3%95%E9%A2%98T1/</url>
<content type="html"><![CDATA[<blockquote><p>猴子登山:有N个台阶,0<N<=50, 猴子每次只跳1个或者3个台阶,输入N, 输出猴子有多少种方式到达台阶终点</p></blockquote><figure class="highlight stata"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><code class="hljs stata"><br><span class="hljs-comment">/*</span><br><span class="hljs-comment"> f1 = 1</span><br><span class="hljs-comment"> f2 = 1</span><br><span class="hljs-comment"> f3 = 2</span><br><span class="hljs-comment"> f4 = f3 + f1 = 3</span><br><span class="hljs-comment"> f5 = f4 + f2 = 4</span><br><span class="hljs-comment"> f6 = f5 + f3 = 6</span><br><span class="hljs-comment"> f7 = f6 + f4 = 9</span><br><span class="hljs-comment"> */</span><br><br>let <span class="hljs-keyword">input</span>: Int = 50<br><br><span class="hljs-keyword">print</span>(<span class="hljs-string">"输入:"</span> + <span class="hljs-built_in">String</span>(<span class="hljs-keyword">input</span>))<br><br><span class="hljs-keyword">var</span> fArray: [Int] = [1, 1, 2]<br><br>func <span class="hljs-built_in">f</span>(f: Int) -> Int {<br> <span class="hljs-keyword">var</span> arr: [Int] = [f]<br> <span class="hljs-keyword">var</span> fc = 0;<br> <span class="hljs-keyword">while</span> true {<br> <span class="hljs-keyword">var</span> arr1: [Int] = [];<br> <span class="hljs-keyword">for</span> fi <span class="hljs-keyword">in</span> arr {<br> <span class="hljs-keyword">if</span> fArray.<span class="hljs-keyword">count</span> >= fi {<br> fc += fArray[fi - 1];<br> } <span class="hljs-keyword">else</span> {<br> arr1.<span class="hljs-keyword">append</span>(fi - 1)<br> arr1.<span class="hljs-keyword">append</span>(fi - 3)<br> }<br> }<br> <span class="hljs-keyword">if</span> arr1.<span class="hljs-keyword">count</span> == 0 {<br> <span class="hljs-keyword">break</span>;<br> }<br> arr = arr1;<br> }<br> <span class="hljs-keyword">return</span> fc<br>}<br><br><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> 4 ... <span class="hljs-keyword">input</span> {<br> fArray.<span class="hljs-keyword">append</span>(<span class="hljs-built_in">f</span>(f: i))<br>}<br><br><span class="hljs-keyword">print</span>(<span class="hljs-string">"输出:"</span> + <span class="hljs-built_in">String</span>(fArray.last!))<br></code></pre></td></tr></table></figure><figure class="highlight dns"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs dns">输入:<span class="hljs-number">50</span><br>输出:<span class="hljs-number">122106097</span><br></code></pre></td></tr></table></figure>]]></content>
<categories>
<category>算法</category>
</categories>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>开源镜像站</title>
<link href="/2021/04/11/%E5%BC%80%E6%BA%90%E9%95%9C%E5%83%8F%E7%AB%99/"/>
<url>/2021/04/11/%E5%BC%80%E6%BA%90%E9%95%9C%E5%83%8F%E7%AB%99/</url>
<content type="html"><![CDATA[<p><a href="https://gems.ruby-china.com/">Ruby China</a></p><p><a href="https://mirrors.tuna.tsinghua.edu.cn/">清华大学开源软件镜像站:https://mirrors.tuna.tsinghua.edu.cn/</a></p><p><a href="http://mirrors.163.com/">网易开源镜像站:http://mirrors.163.com/</a></p><p><a href="https://mirrors.cloud.tencent.com/">腾讯软件源:https://mirrors.cloud.tencent.com/</a></p><p><a href="https://mirrors.nju.edu.cn/">南京大学开源镜像站:https://mirrors.nju.edu.cn/</a></p>]]></content>
<categories>
<category>开源镜像站</category>
</categories>
<tags>
<tag>CocoaPods</tag>
</tags>
</entry>
<entry>
<title>iOS和Flutter混合开发</title>
<link href="/2021/04/11/iOS%E5%92%8CFlutter%E6%B7%B7%E5%90%88%E5%BC%80%E5%8F%91/"/>
<url>/2021/04/11/iOS%E5%92%8CFlutter%E6%B7%B7%E5%90%88%E5%BC%80%E5%8F%91/</url>
<content type="html"><![CDATA[<p>参考官方文档:</p><p><a href="https://flutter.cn/docs/development/add-to-app">https://flutter.cn/docs/development/add-to-app</a></p><p><a href="https://flutter.dev/docs/development/add-to-app">https://flutter.dev/docs/development/add-to-app/</a></p><h3 id="一、创建并集成"><a href="#一、创建并集成" class="headerlink" title="一、创建并集成"></a>一、创建并集成</h3><ol><li>使用命令行为原生工程创建<code>flutter</code>模块</li></ol><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs cpp">flutter create --<span class="hljs-keyword">template</span> <span class="hljs-keyword">module</span> FlutterProject<br></code></pre></td></tr></table></figure><ol start="2"><li>使用<code>CocoaPods</code>集成源码</li></ol><figure class="highlight pgsql"><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><code class="hljs pgsql">flutter_application_path = <span class="hljs-string">'../FlutterProject'</span><br><span class="hljs-keyword">load</span> File.<span class="hljs-keyword">join</span>(flutter_application_path, <span class="hljs-string">'.ios'</span>, <span class="hljs-string">'Flutter'</span>, <span class="hljs-string">'podhelper.rb'</span>)<br><br>target <span class="hljs-string">'NativeProject'</span> <span class="hljs-keyword">do</span><br> install_all_flutter_pods(flutter_application_path)<br><span class="hljs-keyword">end</span><br></code></pre></td></tr></table></figure><ol start="3"><li>使用命令行打包成<code>framework</code>集成</li></ol><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs awk">flutter build ios-framework --output=some<span class="hljs-regexp">/path/</span>MyApp<span class="hljs-regexp">/Flutter/</span><br>flutter build ios-framework --cocoapods --output=some<span class="hljs-regexp">/path/</span>MyApp<span class="hljs-regexp">/Flutter/</span><br></code></pre></td></tr></table></figure><p>命令行中加入<code>--cocoapods</code>参数会输出<code>Flutter.podspec</code>替代<code>Flutter.framework</code>,该<code>podspec</code>中为官方提供的<code>Flutter.framework</code>的集成地址,方便用户集成</p><h3 id="二、iOS和Flutter混合开发交互方案"><a href="#二、iOS和Flutter混合开发交互方案" class="headerlink" title="二、iOS和Flutter混合开发交互方案"></a>二、iOS和Flutter混合开发交互方案</h3><h4 id="1、路由管理"><a href="#1、路由管理" class="headerlink" title="1、路由管理"></a>1、路由管理</h4><ol><li>官方方法</li></ol><p><code>FlutterEngine</code>是官方提供的管理类,推荐在<code>App</code>启动时初始化,由于该类占用内存较多,所以推荐只创建一次,每个<code>Flutter</code>页面都使用同一个<code>FlutterEngine</code>初始化</p><p><code>FlutterViewController</code>是官方提供的控制器,集成<code>UIViewController</code>,推荐使用如下方法初始化</p><figure class="highlight less"><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></pre></td><td class="code"><pre><code class="hljs less"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * Initializes this FlutterViewController with the specified `FlutterEngine`.</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * The initialized viewcontroller will attach itself to the engine as part of this process.</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * @param engine The `FlutterEngine` instance to attach to. Cannot be nil.</span><br><span class="hljs-comment"> * @param nibName The NIB name to initialize this UIViewController with.</span><br><span class="hljs-comment"> * @param nibBundle The NIB bundle.</span><br><span class="hljs-comment"> */</span><br><span class="hljs-selector-tag">-</span> (instancetype)<span class="hljs-selector-tag">initWithEngine</span>:(FlutterEngine*)<span class="hljs-selector-tag">engine</span><br> <span class="hljs-selector-tag">nibName</span>:(nullable NSString*)<span class="hljs-selector-tag">nibName</span><br> <span class="hljs-selector-tag">bundle</span>:(nullable NSBundle*)<span class="hljs-selector-tag">nibBundle</span> <span class="hljs-selector-tag">NS_DESIGNATED_INITIALIZER</span>;<br></code></pre></td></tr></table></figure><blockquote><p>注:官方文档中的隐式<code>FlutterEngine</code>创建<code>FlutterViewController</code>的方法会产生新的<code>FlutterEngine</code>,不推荐使用</p></blockquote><p>使用推荐方法创建的<code>FlutterViewController</code>默认加载的<code>Flutter</code>端<code>main.dart</code>中的<code>main()</code>方法,所以会直接展示对应绑定的页面</p><p>针对如上流程,当原生打开指定的<code>Flutter</code>页面时,初始化<code>FlutterViewController</code>后,使用<code>pushRoute</code>方法定位到对应的页面</p><figure class="highlight gcode"><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></pre></td><td class="code"><pre><code class="hljs gcode"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * Instructs the Flutter Navigator (if any) to go back.</span><br><span class="hljs-comment"> */</span><br>- <span class="hljs-comment">(void)</span>popRoute;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * Instructs the Flutter Navigator (if any) to push a route on to the navigation</span><br><span class="hljs-comment"> * stack.</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * @param route The name of the route to push to the navigation stack.</span><br><span class="hljs-comment"> */</span><br>- <span class="hljs-comment">(void)</span>pushRoute:<span class="hljs-comment">(NSString*)</span>route;<br></code></pre></td></tr></table></figure><blockquote><p>注:<code>pushRoute</code>方法定位页面后,<code>main.dart</code>中的<code>main()</code>方法绑定的初始页面依然存在,所以在需要退出<code>Flutter</code>页面时,直接从原生关闭</p></blockquote><p>相连多个<code>Flutter</code>页面之间建议仍然使用同一个<code>controller</code>,减少内存占用,便于整体状态(例如:黑暗模式等)维护</p><ol start="2"><li>第三方插件<code>flutter_boost</code></li></ol><p><code>flutter_boost</code>是咸鱼团队开发的针对<code>flutter</code>混合开发的插件,能像原生一样直接打开相应的<code>flutter</code>页面,并且集成了对原生<code>App</code>前后台状态的监听和原生控制器的生命周期的监听,功能较为完善,混合开发推荐使用</p><figure class="highlight php"><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></pre></td><td class="code"><pre><code class="hljs php"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 初始化FlutterBoost混合栈环境。应在程序使用混合栈之前调用。如在AppDelegate中。本函数默认需要flutter boost来注册所有插件。</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> platform 平台层实现FLBPlatform的对象</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> callback 启动之后回调</span><br><span class="hljs-comment"> */</span><br>- (<span class="hljs-keyword">void</span>)startFlutterWithPlatform:(id<FLBPlatform>)platform<br> onStart:(<span class="hljs-keyword">void</span> (^)(FlutterEngine *engine))callback;<br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 初始化FlutterBoost混合栈环境。应在程序使用混合栈之前调用。如在AppDelegate中。本函数默认需要flutter boost来注册所有插件。</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> platform 平台层实现FLBPlatform的对象</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> engine 外部实例化engine后传入</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> callback 启动之后回调</span><br><span class="hljs-comment"> */</span><br>- (<span class="hljs-keyword">void</span>)startFlutterWithPlatform:(id<FLBPlatform>)platform<br> engine:(FlutterEngine* _Nullable)engine<br> onStart:(<span class="hljs-keyword">void</span> (^)(FlutterEngine *engine))callback;<br></code></pre></td></tr></table></figure><h4 id="2、FlutterMethodChannel通信"><a href="#2、FlutterMethodChannel通信" class="headerlink" title="2、FlutterMethodChannel通信"></a>2、FlutterMethodChannel通信</h4><p><code>FlutterMethodChannel</code>是官方提供的原生和<code>Flutter</code>通信的工具,支持双向通信,通过该实例对象,触发方法,推荐使用单例持久化</p><p>通过<code>FlutterMethodChannel</code>可以实现对原生容器的修改,包括打开原生页面等</p><figure class="highlight less"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs less"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * Invokes the specified Flutter method with the specified arguments, expecting</span><br><span class="hljs-comment"> * an asynchronous result.</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * @param method The name of the method to invoke.</span><br><span class="hljs-comment"> * @param arguments The arguments. Must be a value supported by the codec of this</span><br><span class="hljs-comment"> * channel.</span><br><span class="hljs-comment"> * @param callback A callback that will be invoked with the asynchronous result.</span><br><span class="hljs-comment"> * The result will be a `FlutterError` instance, if the method call resulted</span><br><span class="hljs-comment"> * in an error on the Flutter side. Will be `FlutterMethodNotImplemented`, if</span><br><span class="hljs-comment"> * the method called was not implemented on the Flutter side. Any other value,</span><br><span class="hljs-comment"> * including `nil`, should be interpreted as successful results.</span><br><span class="hljs-comment"> */</span><br><span class="hljs-selector-tag">-</span> (void)<span class="hljs-selector-tag">invokeMethod</span>:(NSString*)<span class="hljs-selector-tag">method</span><br> <span class="hljs-selector-tag">arguments</span>:(id _Nullable)<span class="hljs-selector-tag">arguments</span><br> <span class="hljs-selector-tag">result</span>:(FlutterResult _Nullable)<span class="hljs-selector-tag">callback</span>;<br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * Registers a handler for method calls from the Flutter side.</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * Replaces any existing handler. Use a `nil` handler for unregistering the</span><br><span class="hljs-comment"> * existing handler.</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * @param handler The method call handler.</span><br><span class="hljs-comment"> */</span><br><span class="hljs-selector-tag">-</span> (void)<span class="hljs-selector-tag">setMethodCallHandler</span>:(FlutterMethodCallHandler _Nullable)<span class="hljs-selector-tag">handler</span>;<br></code></pre></td></tr></table></figure><h3 id="三、flutter-boost参考代码"><a href="#三、flutter-boost参考代码" class="headerlink" title="三、flutter_boost参考代码"></a>三、<code>flutter_boost</code>参考代码</h3><p>详细内容见<code>github</code><a href="https://github.com/AnderGH/GH_OCFlutterHybird">项目源码</a></p>]]></content>
<categories>
<category>flutter</category>
</categories>
<tags>
<tag>iOS</tag>
<tag>CocoaPods</tag>
<tag>flutter</tag>
</tags>
</entry>
<entry>
<title>新主题fluid</title>
<link href="/2021/04/11/%E6%96%B0%E4%B8%BB%E9%A2%98fluid/"/>
<url>/2021/04/11/%E6%96%B0%E4%B8%BB%E9%A2%98fluid/</url>
<content type="html"><![CDATA[<h3 id="一、环境升级"><a href="#一、环境升级" class="headerlink" title="一、环境升级"></a>一、环境升级</h3><p>本次升级本地环境,同时重新选择适配的主题,环境如下:</p><ul><li><code>node.js v14.16.0</code></li><li><code>npm 6.14.11</code></li><li><code>hexo 5.4.0</code></li><li><code>hexo-cli 4.2.0</code></li></ul><p>新主题下载地址:<a href="https://github.com/fluid-dev/hexo-theme-fluid">https://github.com/fluid-dev/hexo-theme-fluid</a></p><h3 id="二、图片加载适配"><a href="#二、图片加载适配" class="headerlink" title="二、图片加载适配"></a>二、图片加载适配</h3><p>本次修改主题直接使用<code>hexo</code>自带的图片语法</p><ol><li>配置文件<code>_config.yml</code>下的属性<code>post_asset_folder: true</code></li><li>使用语法<code>![image_1.png](image_1.png)</code>语法加载</li></ol><p>或者直接使用<code>img</code>标签</p><h3 id="三、音乐加载"><a href="#三、音乐加载" class="headerlink" title="三、音乐加载"></a>三、音乐加载</h3><p>使用开源播放器插件<a href="https://github.com/MoePlayer/hexo-tag-aplayer">hexo-tag-aplayer</a>和插件<a href="https://github.com/MoePlayer/APlayer-Typecho">APlayer-Typecho</a></p><link rel="stylesheet" href="/dist/APlayer.min.css"><script src="/dist/APlayer.min.js"></script><div class="aplayer" data-id="1808492017" data-server="netease" data-type="song"></div><script src="/dist/Meting.min.js"></script><h3 id="四、视频加载"><a href="#四、视频加载" class="headerlink" title="四、视频加载"></a>四、视频加载</h3><p>仍然使用<code>iframe</code>外链</p>]]></content>
<categories>
<category>Hexo</category>
</categories>
<tags>
<tag>Hexo</tag>
</tags>
</entry>
<entry>
<title>iOS无痕埋点实现</title>
<link href="/2020/05/25/iOS%E6%97%A0%E7%97%95%E5%9F%8B%E7%82%B9%E5%AE%9E%E7%8E%B0/"/>
<url>/2020/05/25/iOS%E6%97%A0%E7%97%95%E5%9F%8B%E7%82%B9%E5%AE%9E%E7%8E%B0/</url>
<content type="html"><![CDATA[<p>参考文章:<a href="https://www.jianshu.com/p/2c68896aeb9b">iOS 无痕埋点解决方案—— AOP 篇(1)</a></p><h3 id="一、AOP面向切面编程"><a href="#一、AOP面向切面编程" class="headerlink" title="一、AOP面向切面编程"></a>一、AOP面向切面编程</h3><p><code>AOP</code>全称叫<code>Aspect-Oriented Programming</code>,中文名叫面向切面编程,在<code>iOS</code>平台中,<code>AOP</code>一般使用<code>Runtime</code>实现</p><h3 id="二、代码实现"><a href="#二、代码实现" class="headerlink" title="二、代码实现"></a>二、代码实现</h3><p>本文<a href="https://github.com/AnderGH/AOPDemo"><code>demo</code></a></p><p>在<code>UIKit</code>提供的用户交互接口里,主要可以分为两种:</p><ul><li><code>Delegate</code>类<code>UITableView、UICollectionView</code>的点击事件,特点是方法名定死,使用<code>weak</code>属性持有响应对象</li><li><code>Target-Action</code>类<code>UIControl、UIGestureRecognizer</code>的回调事件,特点是方法名可自定义,方法参数可有可无,使用<code>weak</code>属性持有响应对象,支持多个响应者</li></ul><h4 id="1、Delegate类的交互"><a href="#1、Delegate类的交互" class="headerlink" title="1、Delegate类的交互"></a>1、Delegate类的交互</h4><p>通常会拦截<code>setDelegate:</code>的方法,此时拦截到的<code>delegate</code>对象即为响应对象,再通过判断该响应对象是否实现了相应的代理方法,构建相同的方法进行交换,网上百度到的大部分都是这种实现的逻辑</p><p>但此方案存在如下问题:</p><ul><li>如果父类实现了<code>setDelegate:</code>和相应的代理方法,而具体的业务逻辑是由子类<code>override</code>重写的代理方法,那么判断到的埋点数据有可能存在问题</li><li>如果同一个页面有多个<code>UITableView</code>,那么<code>setDelegate:</code>方法也会实现多次,此时需要防止出现多重交换的情况</li></ul><p>参考文章中给出了其他方案:</p><ol><li>拦截<code>setDelegate:</code>方法,重新创建一个<code>proxy</code>类绑定代理并实现相应的代理方法,并将该<code>proxy</code>类的对象交换给系统的<code>delegate</code></li><li>使用<code>Runtime</code>将自定义的<code>proxy</code>类的对象添加到控件中持有</li><li>当触发代理方法时,系统实际持有<code>delegate</code>属性是<code>proxy</code>类的对应,会将触发方法发送到<code>proxy</code>类中,此时就可以进一步判断是否需要将代理方法继续转发到业务层</li></ol><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br></pre></td><td class="code"><pre><code class="hljs swift"><span class="hljs-keyword">import</span> UIKit<br><br><span class="hljs-comment">/// 使用此类替代系统的delegate</span><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GHUITableViewDelegateProxy</span>: <span class="hljs-title">NSObject</span>, <span class="hljs-title">UITableViewDelegate</span> </span>{<br> <br> <span class="hljs-keyword">weak</span> <span class="hljs-keyword">var</span> delegate: <span class="hljs-type">UITableViewDelegate</span>?<br> <br> <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">responds</span>(<span class="hljs-params">to</span> <span class="hljs-params">aSelector</span>: <span class="hljs-type">Selector</span>!)</span> -> <span class="hljs-type">Bool</span> {<br> <span class="hljs-keyword">var</span> hasSelector: <span class="hljs-type">Bool</span> <span class="hljs-operator">=</span> <span class="hljs-literal">false</span><br> <span class="hljs-keyword">if</span> <span class="hljs-keyword">self</span>.delegate <span class="hljs-operator">==</span> <span class="hljs-literal">nil</span> {<br> <span class="hljs-keyword">return</span> hasSelector<br> }<br> hasSelector <span class="hljs-operator">=</span> <span class="hljs-keyword">self</span>.delegate<span class="hljs-operator">?</span>.responds(to: aSelector) <span class="hljs-operator">??</span> <span class="hljs-literal">true</span><br> <span class="hljs-keyword">return</span> hasSelector<br> }<br> <br> <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">forwardingTarget</span>(<span class="hljs-params">for</span> <span class="hljs-params">aSelector</span>: <span class="hljs-type">Selector</span>!)</span> -> <span class="hljs-keyword">Any</span><span class="hljs-operator">?</span> {<br> <span class="hljs-keyword">if</span> <span class="hljs-keyword">self</span>.delegate <span class="hljs-operator">==</span> <span class="hljs-literal">nil</span> {<br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.forwardingTarget(for: aSelector)<br> }<br> <span class="hljs-keyword">if</span> <span class="hljs-keyword">self</span>.delegate<span class="hljs-operator">?</span>.responds(to: aSelector) <span class="hljs-operator">==</span> <span class="hljs-literal">false</span> {<br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.forwardingTarget(for: aSelector)<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">self</span>.delegate<br> }<br> <br> <span class="hljs-comment">// MARK: UITableViewDelegate</span><br> <br> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">tableView</span>(<span class="hljs-keyword">_</span> <span class="hljs-params">tableView</span>: <span class="hljs-type">UITableView</span>, <span class="hljs-params">didSelectRowAt</span> <span class="hljs-params">indexPath</span>: <span class="hljs-type">IndexPath</span>)</span> {<br> <br> <span class="hljs-keyword">if</span> <span class="hljs-keyword">self</span>.delegate <span class="hljs-operator">==</span> <span class="hljs-literal">nil</span> {<br> <span class="hljs-keyword">return</span><br> }<br> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">self</span>.delegate<span class="hljs-operator">?</span>.responds(to: #selector(tableView(<span class="hljs-keyword">_</span>:didSelectRowAt:)))) <span class="hljs-operator">==</span> <span class="hljs-literal">false</span> {<br> <span class="hljs-keyword">return</span><br> }<br> <br> <span class="hljs-type">UITableViewTrack</span>.shared.trackTableView(tableView, didSelectRowAt: indexPath)<br> <br> <span class="hljs-keyword">self</span>.delegate<span class="hljs-operator">?</span>.tableView<span class="hljs-operator">?</span>(tableView, didSelectRowAt: indexPath)<br> }<br>}<br><br><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">swizzle</span>(<span class="hljs-keyword">_</span> <span class="hljs-params">tableView</span>: <span class="hljs-type">UITableView</span>.<span class="hljs-keyword">Type</span>)</span> {<br> <span class="hljs-keyword">let</span> selectors: <span class="hljs-type">Array</span><<span class="hljs-type">Array</span><<span class="hljs-type">Selector</span>>> <span class="hljs-operator">=</span> [<br> [<br> <span class="hljs-keyword">#selector</span>(setter: tableView.delegate),<br> <span class="hljs-keyword">#selector</span>(tableView.gh_setDelegate(<span class="hljs-keyword">_</span>:))<br> ],<br> ]<br> <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> selectors {<br> <span class="hljs-keyword">let</span> originalSelector: <span class="hljs-type">Selector</span> <span class="hljs-operator">=</span> item[<span class="hljs-number">0</span>]<br> <span class="hljs-keyword">let</span> swizzledSelector: <span class="hljs-type">Selector</span> <span class="hljs-operator">=</span> item[<span class="hljs-number">1</span>]<br><br> <span class="hljs-keyword">let</span> originalMethod: <span class="hljs-type">Method</span>? <span class="hljs-operator">=</span> class_getInstanceMethod(tableView, originalSelector)<br> <span class="hljs-keyword">let</span> swizzledMethod: <span class="hljs-type">Method</span>? <span class="hljs-operator">=</span> class_getInstanceMethod(tableView, swizzledSelector)<br> <br> <span class="hljs-keyword">if</span> originalMethod <span class="hljs-operator">==</span> <span class="hljs-literal">nil</span> {<br> <span class="hljs-keyword">continue</span><br> }<br> <br> <span class="hljs-keyword">let</span> didAddMethod: <span class="hljs-type">Bool</span> <span class="hljs-operator">=</span> class_addMethod(tableView, originalSelector, method_getImplementation(swizzledMethod<span class="hljs-operator">!</span>), method_getTypeEncoding(swizzledMethod<span class="hljs-operator">!</span>))<br> <span class="hljs-keyword">if</span> didAddMethod {<br> class_replaceMethod(tableView, swizzledSelector, method_getImplementation(originalMethod<span class="hljs-operator">!</span>), method_getTypeEncoding(originalMethod<span class="hljs-operator">!</span>))<br> } <span class="hljs-keyword">else</span> {<br> method_exchangeImplementations(originalMethod<span class="hljs-operator">!</span>, swizzledMethod<span class="hljs-operator">!</span>)<br> }<br> }<br>}<br><br><span class="hljs-keyword">var</span> ghUITableViewDelegateProxyKey <span class="hljs-operator">=</span> <span class="hljs-string">"GHUITableViewDelegateProxyKey"</span><br><br><span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">UITableView</span> </span>{<br> <br> <span class="hljs-keyword">var</span> ghUITableViewDelegateProxy: <span class="hljs-type">GHUITableViewDelegateProxy</span>? {<br> <span class="hljs-keyword">set</span> {<br> objc_setAssociatedObject(<span class="hljs-keyword">self</span>, <span class="hljs-operator">&</span>ghUITableViewDelegateProxyKey, newValue, objc_AssociationPolicy.<span class="hljs-type">OBJC_ASSOCIATION_RETAIN</span>)<br> }<br> <span class="hljs-keyword">get</span> {<br> <span class="hljs-keyword">return</span> objc_getAssociatedObject(<span class="hljs-keyword">self</span>, <span class="hljs-operator">&</span>ghUITableViewDelegateProxyKey) <span class="hljs-keyword">as?</span> <span class="hljs-type">GHUITableViewDelegateProxy</span><br> }<br> }<br> <br> <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">let</span> dispatchOnceTime: <span class="hljs-type">Void</span> <span class="hljs-operator">=</span> {<br> swizzle(<span class="hljs-type">UITableView</span>.<span class="hljs-keyword">self</span>)<br> }()<br> <br> <span class="hljs-keyword">@objc</span> <span class="hljs-keyword">open</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">func</span> <span class="hljs-title">startAOP</span>() </span>{<br> <span class="hljs-keyword">guard</span> <span class="hljs-keyword">self</span> <span class="hljs-operator">===</span> <span class="hljs-type">UITableView</span>.<span class="hljs-keyword">self</span> <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> }<br> <span class="hljs-type">UITableView</span>.dispatchOnceTime<br> }<br> <br> <span class="hljs-comment">// MARK: 交换的方法</span><br> <br> <span class="hljs-comment">// 交换setdelegate的方法</span><br> <span class="hljs-keyword">@objc</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">gh_setDelegate</span>(<span class="hljs-keyword">_</span> <span class="hljs-params">delegate</span>: <span class="hljs-type">UITableViewDelegate</span>?)</span> {<br> <br> <span class="hljs-comment">// 使用GHUITableViewDelegateProxy替代原来系统的UITableViewDelegate</span><br> <span class="hljs-keyword">self</span>.ghUITableViewDelegateProxy <span class="hljs-operator">=</span> <span class="hljs-type">GHUITableViewDelegateProxy</span>()<br> <span class="hljs-keyword">self</span>.ghUITableViewDelegateProxy<span class="hljs-operator">?</span>.delegate <span class="hljs-operator">=</span> delegate<br> <br> <span class="hljs-keyword">self</span>.gh_setDelegate(<span class="hljs-keyword">self</span>.ghUITableViewDelegateProxy)<br> }<br>}<br><br></code></pre></td></tr></table></figure><h4 id="2、Target-Action类的交互"><a href="#2、Target-Action类的交互" class="headerlink" title="2、Target-Action类的交互"></a>2、Target-Action类的交互</h4><p><img src="image_1.png" alt="image_1.png"></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><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br></pre></td><td class="code"><pre><code class="hljs swift"><span class="hljs-keyword">import</span> UIKit<br><br><span class="hljs-comment">/// 自定义一个action类,由此类的实例对象替代外部传入的action</span><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GHUITapGestureRecognizerAction</span>: <span class="hljs-title">NSObject</span> </span>{<br> <br> <span class="hljs-comment">// 弱应用,防止循环应用</span><br> <span class="hljs-keyword">weak</span> <span class="hljs-keyword">var</span> target: <span class="hljs-type">UIResponder</span>?<br> <span class="hljs-keyword">var</span> action: <span class="hljs-type">Selector</span>?<br> <br> <span class="hljs-keyword">@objc</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">ghGestureRecognizerAction</span>(<span class="hljs-params">sender</span>: <span class="hljs-type">UIGestureRecognizer</span>?)</span> -> <span class="hljs-type">Void</span> {<br> <span class="hljs-keyword">if</span> <span class="hljs-keyword">self</span>.target <span class="hljs-operator">==</span> <span class="hljs-literal">nil</span> {<br> <span class="hljs-keyword">return</span><br> }<br> <span class="hljs-keyword">if</span> <span class="hljs-keyword">self</span>.action <span class="hljs-operator">==</span> <span class="hljs-literal">nil</span> {<br> <span class="hljs-keyword">return</span><br> }<br> <br> <span class="hljs-type">UITapGestureRecognizerTrack</span>.shared.trackGRAction(sender <span class="hljs-keyword">as?</span> <span class="hljs-type">UITapGestureRecognizer</span>, action: <span class="hljs-keyword">self</span>.action<span class="hljs-operator">!</span>, target: <span class="hljs-keyword">self</span>.target)<br> <br> <span class="hljs-keyword">if</span> ((target<span class="hljs-operator">?</span>.responds(to: action)) <span class="hljs-operator">==</span> <span class="hljs-literal">true</span>) {<br> target<span class="hljs-operator">?</span>.perform(action, with: sender)<br> }<br> }<br>}<br><br><span class="hljs-keyword">var</span> ghGestureActionsKey: <span class="hljs-type">String</span> <span class="hljs-operator">=</span> <span class="hljs-string">"GHGestureActionsKey"</span><br><br><span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">UIResponder</span> </span>{<br> <span class="hljs-comment">/// 使用runtime给UIResponder扩展一个属性</span><br> <span class="hljs-keyword">var</span> ghGestureActions: <span class="hljs-type">Array</span><<span class="hljs-type">GHUITapGestureRecognizerAction</span>>? {<br> <span class="hljs-keyword">set</span> {<br> objc_setAssociatedObject(<span class="hljs-keyword">self</span>, <span class="hljs-operator">&</span>ghGestureActionsKey, newValue, objc_AssociationPolicy.<span class="hljs-type">OBJC_ASSOCIATION_RETAIN</span>)<br> }<br> <span class="hljs-keyword">get</span> {<br> <span class="hljs-keyword">return</span> objc_getAssociatedObject(<span class="hljs-keyword">self</span>, <span class="hljs-operator">&</span>ghGestureActionsKey) <span class="hljs-keyword">as?</span> <span class="hljs-type">Array</span><<span class="hljs-type">GHUITapGestureRecognizerAction</span>><br> }<br> }<br>}<br><br><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">swizzle</span>(<span class="hljs-keyword">_</span> <span class="hljs-params">gesture</span>: <span class="hljs-type">UITapGestureRecognizer</span>.<span class="hljs-keyword">Type</span>)</span> {<br> <span class="hljs-keyword">let</span> selectors: <span class="hljs-type">Array</span><<span class="hljs-type">Array</span><<span class="hljs-type">Selector</span>>> <span class="hljs-operator">=</span> [<br> [<br> <span class="hljs-keyword">#selector</span>(<span class="hljs-type">UITapGestureRecognizer</span>.<span class="hljs-keyword">init</span>(target:action:)),<br> <span class="hljs-keyword">#selector</span>(gesture.gh_init(target:action:))<br> ],<br> [<br> <span class="hljs-keyword">#selector</span>(gesture.addTarget(<span class="hljs-keyword">_</span>:action:)),<br> <span class="hljs-keyword">#selector</span>(gesture.gh_addTarget(<span class="hljs-keyword">_</span>:action:))<br> ],<br> ]<br> <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> selectors {<br> <span class="hljs-keyword">let</span> originalSelector: <span class="hljs-type">Selector</span> <span class="hljs-operator">=</span> item[<span class="hljs-number">0</span>]<br> <span class="hljs-keyword">let</span> swizzledSelector: <span class="hljs-type">Selector</span> <span class="hljs-operator">=</span> item[<span class="hljs-number">1</span>]<br> <br> <span class="hljs-keyword">let</span> originalMethod: <span class="hljs-type">Method</span>? <span class="hljs-operator">=</span> class_getInstanceMethod(gesture, originalSelector)<br> <span class="hljs-keyword">let</span> swizzledMethod: <span class="hljs-type">Method</span>? <span class="hljs-operator">=</span> class_getInstanceMethod(gesture, swizzledSelector)<br> <br> <span class="hljs-keyword">if</span> originalMethod <span class="hljs-operator">==</span> <span class="hljs-literal">nil</span> {<br> <span class="hljs-keyword">continue</span><br> }<br> <br> <span class="hljs-keyword">let</span> didAddMethod: <span class="hljs-type">Bool</span> <span class="hljs-operator">=</span> class_addMethod(gesture, originalSelector, method_getImplementation(swizzledMethod<span class="hljs-operator">!</span>), method_getTypeEncoding(swizzledMethod<span class="hljs-operator">!</span>))<br> <span class="hljs-keyword">if</span> didAddMethod {<br> class_replaceMethod(gesture, swizzledSelector, method_getImplementation(originalMethod<span class="hljs-operator">!</span>), method_getTypeEncoding(originalMethod<span class="hljs-operator">!</span>))<br> } <span class="hljs-keyword">else</span> {<br> method_exchangeImplementations(originalMethod<span class="hljs-operator">!</span>, swizzledMethod<span class="hljs-operator">!</span>)<br> }<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">UITapGestureRecognizer</span> </span>{<br> <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">let</span> dispatchOnceTime: <span class="hljs-type">Void</span> <span class="hljs-operator">=</span> {<br> swizzle(<span class="hljs-type">UITapGestureRecognizer</span>.<span class="hljs-keyword">self</span>)<br> }()<br> <br> <span class="hljs-keyword">@objc</span> <span class="hljs-keyword">open</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">func</span> <span class="hljs-title">startAOP</span>() </span>{<br> <span class="hljs-keyword">guard</span> <span class="hljs-keyword">self</span> <span class="hljs-operator">===</span> <span class="hljs-type">UITapGestureRecognizer</span>.<span class="hljs-keyword">self</span> <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> }<br> <span class="hljs-type">UITapGestureRecognizer</span>.dispatchOnceTime<br> }<br> <br> <span class="hljs-comment">// MARK: 交换的方法</span><br> <br> <span class="hljs-keyword">@objc</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">gh_init</span>(<span class="hljs-params">target</span>: <span class="hljs-keyword">Any</span><span class="hljs-operator">?</span>, <span class="hljs-params">action</span>: <span class="hljs-type">Selector</span>?)</span> -> <span class="hljs-type">UIGestureRecognizer</span> {<br> <span class="hljs-keyword">if</span> target <span class="hljs-operator">==</span> <span class="hljs-literal">nil</span> {<br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">self</span>.gh_init(target: target, action: action);<br> }<br> <span class="hljs-keyword">if</span> (target <span class="hljs-keyword">as?</span> <span class="hljs-type">UIResponder</span>) <span class="hljs-operator">==</span> <span class="hljs-literal">nil</span> {<br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">self</span>.gh_init(target: target, action: action);<br> }<br> <br> <span class="hljs-comment">// 初始化判断</span><br> <span class="hljs-keyword">if</span> (target <span class="hljs-keyword">as?</span> <span class="hljs-type">UIResponder</span>)<span class="hljs-operator">?</span>.ghGestureActions <span class="hljs-operator">==</span> <span class="hljs-literal">nil</span> {<br> (target <span class="hljs-keyword">as?</span> <span class="hljs-type">UIResponder</span>)<span class="hljs-operator">?</span>.ghGestureActions <span class="hljs-operator">=</span> []<br> }<br> <br> <span class="hljs-comment">// 一个手势对应一个GHUITapGestureRecognizerAction属性,再由target去强制有所有的GHUITapGestureRecognizerAction</span><br> <span class="hljs-keyword">let</span> ghAction <span class="hljs-operator">=</span> <span class="hljs-type">GHUITapGestureRecognizerAction</span>()<br> ghAction.target <span class="hljs-operator">=</span> (target <span class="hljs-keyword">as?</span> <span class="hljs-type">UIResponder</span>)<br> ghAction.action <span class="hljs-operator">=</span> action<br> <br> (target <span class="hljs-keyword">as?</span> <span class="hljs-type">UIResponder</span>)<span class="hljs-operator">?</span>.ghGestureActions<span class="hljs-operator">?</span>.append(ghAction)<br> <br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">self</span>.gh_init(target: ghAction, action: #selector(ghAction.ghGestureRecognizerAction(sender:)))<br> }<br> <br> <span class="hljs-keyword">@objc</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">gh_addTarget</span>(<span class="hljs-keyword">_</span> <span class="hljs-params">target</span>: <span class="hljs-keyword">Any</span>, <span class="hljs-params">action</span>: <span class="hljs-type">Selector</span>)</span> {<br> <span class="hljs-keyword">if</span> (target <span class="hljs-keyword">as?</span> <span class="hljs-type">UIResponder</span>) <span class="hljs-operator">==</span> <span class="hljs-literal">nil</span> {<br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">self</span>.gh_addTarget(target, action: action);<br> }<br> <br> <span class="hljs-keyword">if</span> (target <span class="hljs-keyword">as?</span> <span class="hljs-type">UIResponder</span>)<span class="hljs-operator">?</span>.ghGestureActions <span class="hljs-operator">==</span> <span class="hljs-literal">nil</span> {<br> (target <span class="hljs-keyword">as?</span> <span class="hljs-type">UIResponder</span>)<span class="hljs-operator">?</span>.ghGestureActions <span class="hljs-operator">=</span> []<br> }<br> <br> <span class="hljs-keyword">let</span> ghAction <span class="hljs-operator">=</span> <span class="hljs-type">GHUITapGestureRecognizerAction</span>()<br> ghAction.target <span class="hljs-operator">=</span> (target <span class="hljs-keyword">as?</span> <span class="hljs-type">UIResponder</span>)<br> ghAction.action <span class="hljs-operator">=</span> action<br> <br> (target <span class="hljs-keyword">as?</span> <span class="hljs-type">UIResponder</span>)<span class="hljs-operator">?</span>.ghGestureActions<span class="hljs-operator">?</span>.append(ghAction)<br> <br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">self</span>.gh_addTarget(ghAction, action: #selector(ghAction.ghGestureRecognizerAction(sender:)))<br> }<br>}<br><br></code></pre></td></tr></table></figure><h3 id="三、第三方库"><a href="#三、第三方库" class="headerlink" title="三、第三方库"></a>三、第三方库</h3><p>很多第三方库也有功能强大的<code>AOP</code>逻辑,本文主要是轻量级的代码实现,其他第三方库暂不做介绍</p>]]></content>
<categories>
<category>iOS</category>
</categories>
<tags>
<tag>iOS</tag>
<tag>Swift</tag>
<tag>AOP</tag>
</tags>
</entry>
<entry>
<title>Flutter注释文档生成</title>
<link href="/2020/04/20/Flutter%E6%B3%A8%E9%87%8A%E6%96%87%E6%A1%A3%E7%94%9F%E6%88%90/"/>
<url>/2020/04/20/Flutter%E6%B3%A8%E9%87%8A%E6%96%87%E6%A1%A3%E7%94%9F%E6%88%90/</url>
<content type="html"><![CDATA[<h3 id="一、注释类别"><a href="#一、注释类别" class="headerlink" title="一、注释类别"></a>一、注释类别</h3><p><code>Dart</code>支持单行注释、多行注释和文档注释,官方提供了相关注释的说明文档<a href="https://dart.dev/guides/language/effective-dart/documentation/"><code>Effective Dart</code></a></p><figure class="highlight awk"><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><code class="hljs awk"><span class="hljs-regexp">//</span> 单行注释<br><br>/*<br>多行注释<br>*/<br> <br>由于历史原因,dartdoc支持两种文档注释语法,(<span class="hljs-regexp">//</span><span class="hljs-regexp">/ “ C#样式”)和/</span>** ... *<span class="hljs-regexp">/(“ JavaDoc样式”),推荐适用/</span><span class="hljs-regexp">//</span><br><span class="hljs-regexp">//</span><span class="hljs-regexp">/ 文档注释</span><br></code></pre></td></tr></table></figure><ul><li>单行注释用法简单,适用于方法、类等内部实现使用,推荐作为内部补充说明</li><li>多行注释一般用于大段说明文字等,不推荐适用</li><li>文档注释以///开头,推荐适用于类、方法等</li></ul><h3 id="二、注释文档生成"><a href="#二、注释文档生成" class="headerlink" title="二、注释文档生成"></a>二、注释文档生成</h3><p><a href="https://dart.cn/tools/dartdoc/"><code>dartdoc</code></a>脚本可以从<code>Dart</code>源代码中提取文档注释生成<code>API</code>参考文档</p><ol><li><code>dart sdk</code>环境</li></ol><p>需要保证本地<code>dart</code>环境正常,如果本地能执行<code>flutter doctor</code>命令,那么就能正常使用<code>dartdoc</code>命令</p><ol start="2"><li>路径</li></ol><p><code>dartdoc</code>脚本在<code>sdk</code>安装包中的路径如下:<code>~/flutter/bin/cache/dart-sdk/bin/dartdoc</code>,请对照本地部署包得到实际路径</p><ol start="3"><li>执行如下命令行</li></ol><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs awk"><span class="hljs-regexp">//</span> 进入flutter工程目录下<br>$ cd ~<span class="hljs-regexp">/Desktop/</span>demo_dartdoc<br></code></pre></td></tr></table></figure><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs awk"><span class="hljs-regexp">//</span> 直接调用sdk中的dartdoc工具<br>$ ~<span class="hljs-regexp">/flutter/</span>bin<span class="hljs-regexp">/cache/</span>dart-sdk<span class="hljs-regexp">/bin/</span>dartdoc<br></code></pre></td></tr></table></figure><ol start="4"><li>打开生成的<code>doc</code>文件夹,可以找到所有生成好的注释文档,其中<code>library</code>即为工程中个性化的类的相关注释说明,或者按照文件夹目录直接打开对应的<code>html</code>文件也可</li></ol>]]></content>
<categories>
<category>flutter</category>
</categories>
<tags>
<tag>flutter</tag>
<tag>dartdoc</tag>
</tags>
</entry>
<entry>
<title>Flutter通知Notification</title>
<link href="/2020/04/16/Flutter%E9%80%9A%E7%9F%A5Notification/"/>
<url>/2020/04/16/Flutter%E9%80%9A%E7%9F%A5Notification/</url>
<content type="html"><![CDATA[<h3 id="一、基本概念"><a href="#一、基本概念" class="headerlink" title="一、基本概念"></a>一、基本概念</h3><ul><li>在<code>widget</code>树中,每一个节点都可以分发通知</li><li>通知会沿着当前节点向上传递,所有父节点都可以通过<code>NotificationListener</code>来监听通知</li><li><code>Flutter</code>中将这种由子向父的传递通知的机制称为通知冒泡<code>Notification Bubbling</code></li><li>通知冒泡和用户触摸事件冒泡是相似的,但有一点不同:通知冒泡可以中止,但用户触摸事件不行</li></ul><h3 id="二、系统通知"><a href="#二、系统通知" class="headerlink" title="二、系统通知"></a>二、系统通知</h3><h4 id="1、接收系统通知"><a href="#1、接收系统通知" class="headerlink" title="1、接收系统通知"></a>1、接收系统通知</h4><blockquote><p>例如:接收<code>ListView</code>的通知</p></blockquote><ol><li><p>首先找到<code>ListView</code>文档,<code>ListView</code>提供了<code>ScrollNotification</code>的通知类,同时有五个子类继承,分别是<code>ScrollStartNotification</code>、<code>ScrollUpdateNotification</code>、<code>OverscrollNotification</code>、<code>ScrollEndNotification</code>、<code>UserScrollNotification</code>,</p></li><li><p>根据如下<code>NotificationListener</code>的注释,可以直接对父类<code>ScrollNotification</code>进行监听,也可以单独对某个通知子类型进行监听</p></li></ol><figure class="highlight scala"><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></pre></td><td class="code"><pre><code class="hljs scala"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NotificationListener<T</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Notification></span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-comment">/// Creates a widget that listens for notifications.</span><br> const <span class="hljs-type">NotificationListener</span>({<br> <span class="hljs-type">Key</span> key,<br> <span class="hljs-meta">@required</span> <span class="hljs-keyword">this</span>.child,<br> <span class="hljs-keyword">this</span>.onNotification,<br> }) : <span class="hljs-keyword">super</span>(key: key);<br><br> ...<br> <span class="hljs-keyword">final</span> <span class="hljs-type">Widget</span> child;<br> ...<br>}<br></code></pre></td></tr></table></figure><ol start="3"><li><p><code>onNotification</code>回调为通知处理的回调,需要有返回值,如果有多层<code>NotificationListener</code>监听,那么当返回值为<code>true</code>时,阻止冒泡,其父级<code>NotificationListener</code>将不再收到子级监听的通知类型,当返回值为<code>false</code>时继续向上冒泡通知</p></li><li><p>代码如下</p></li></ol><figure class="highlight scala"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs scala"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_MyHomePageState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<MyHomePage></span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(widget.title),<br> ),<br> body: <span class="hljs-type">NotificationListener</span><<span class="hljs-type">ScrollStartNotification</span>>(<br> onNotification: (notification) {<br> print('父级监听开始滚动');<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br> },<br> child: <span class="hljs-type">NotificationListener</span><<span class="hljs-type">ScrollStartNotification</span>>(<br> onNotification: (notification) {<br> print('子级监听开始滚动');<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br> },<br> child: <span class="hljs-type">ListView</span>.builder(<br> itemBuilder: (context, index) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">ListTile</span>(<br> title: <span class="hljs-type">Text</span>(index.toString()),<br> );<br> },<br> itemCount: <span class="hljs-number">100</span>,<br> ),<br> ),<br> ),<br> );<br> }<br>}<br></code></pre></td></tr></table></figure><h4 id="2、自定义通知"><a href="#2、自定义通知" class="headerlink" title="2、自定义通知"></a>2、自定义通知</h4><figure class="highlight scala"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><code class="hljs scala"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Page1</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> _Page1State createState() => _Page1State();<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_Page1State</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<Page1></span> </span>{<br> <span class="hljs-type">String</span> _msg = <span class="hljs-string">""</span>;<br><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(<span class="hljs-symbol">'page</span>1'),<br> ),<br> body: <span class="hljs-type">NotificationListener</span><<span class="hljs-type">MyNotification</span>>(<br> onNotification: (notification) {<br> setState(() {<br> _msg += notification.msg + <span class="hljs-string">" "</span>;<br> });<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br> },<br> child: <span class="hljs-type">Center</span>(<br> child: <span class="hljs-type">Column</span>(<br> mainAxisSize: <span class="hljs-type">MainAxisSize</span>.min,<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">Text</span>(_msg),<br> <span class="hljs-type">Builder</span>(<br> builder: (context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">RaisedButton</span>(<br> <span class="hljs-comment">// 按钮点击时分发通知</span><br> onPressed: () {<br> <span class="hljs-type">MyNotification</span>(<span class="hljs-string">"Hi"</span>).dispatch(context);<br> },<br> child: <span class="hljs-type">Text</span>(<span class="hljs-string">"Send Notification"</span>),<br> );<br> },<br> ),<br> ],<br> ),<br> ),<br> ),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyNotification</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Notification</span> </span>{<br> <span class="hljs-type">MyNotification</span>(<span class="hljs-keyword">this</span>.msg);<br> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> msg;<br>}<br><br></code></pre></td></tr></table></figure><ul><li>需要顶一个继承于<code>Notification</code>的通知类型</li><li>使用<code>NotificationListener</code>对自定义的通知类型进行监听</li><li>使用<code>dispatch</code>方法触发通知,此方法中的<code>BuildContext</code>参数必须是当前节点,不能使用超过<code>NotificationListener</code>的父节点</li></ul><h3 id="三、通知冒泡原理"><a href="#三、通知冒泡原理" class="headerlink" title="三、通知冒泡原理"></a>三、通知冒泡原理</h3><figure class="highlight dart"><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><code class="hljs dart"><span class="hljs-built_in">bool</span> _dispatch(Notification notification, <span class="hljs-built_in">Element</span> element) {<br> <span class="hljs-comment">// 如果通知监听器不为空,并且当前通知类型是该NotificationListener</span><br> <span class="hljs-comment">// 监听的通知类型,则调用当前NotificationListener的onNotification</span><br> <span class="hljs-keyword">if</span> (onNotification != <span class="hljs-keyword">null</span> && notification <span class="hljs-keyword">is</span> T) {<br> <span class="hljs-keyword">final</span> <span class="hljs-built_in">bool</span> result = onNotification(notification);<br> <span class="hljs-comment">// 返回值决定是否继续向上遍历</span><br> <span class="hljs-keyword">return</span> result == <span class="hljs-keyword">true</span>; <br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;<br>}<br></code></pre></td></tr></table></figure><p>可以看到<code>NotificationListener</code>的<code>onNotification</code>回调最终是在<code>_dispatch</code>方法中执行的,然后会根据返回值来确定是否继续向上冒泡,此处不再深究</p>]]></content>
<categories>
<category>flutter</category>
</categories>
<tags>
<tag>flutter</tag>
<tag>Notification</tag>
</tags>
</entry>
<entry>
<title>Dart单例模式</title>
<link href="/2020/03/27/Dart%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/"/>
<url>/2020/03/27/Dart%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/</url>
<content type="html"><![CDATA[<h4 id="一、几个知识点"><a href="#一、几个知识点" class="headerlink" title="一、几个知识点"></a>一、几个知识点</h4><ul><li>当使用<code>factory</code>关键词修饰构造函数时,这个构造函数不会创建类的实例</li><li>使用<code>new</code>语句来构造一个类,构造函数的名字可能是<code>ClassName</code>,也可以是<code>ClassName.otherName</code>,关键字<code>new</code>可以省略</li><li><code>Dart</code>没有关键字<code>public</code>、<code>protected</code>和<code>private</code>,如果标识符以下划线<code>_</code>开头,则它相对于库是私有的,每个<code>.dart</code>文件都是一个库</li></ul><h4 id="二、代码"><a href="#二、代码" class="headerlink" title="二、代码"></a>二、代码</h4><figure class="highlight reasonml"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs reasonml"><br><span class="hljs-keyword">class</span> SingletonClass {<br> <span class="hljs-comment">// 单例中的参数</span><br> String params1;<br><br> <span class="hljs-comment">// 静态变量</span><br> static SingletonClass _instance;<br> <span class="hljs-comment">// 使用factory修饰无名构造函数,不创建新的实例,直接导向sharedInstance方法,也可以直接删除无名构造函数的方法</span><br> factory <span class="hljs-constructor">SingletonClass()</span> {<br> return <span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">SingletonClass</span>.</span></span>shared<span class="hljs-constructor">Instance()</span>;<br> }<br> <span class="hljs-comment">// 指定私有构造函数作为唯一初始化入口</span><br> <span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">SingletonClass</span>.</span><span class="hljs-module"><span class="hljs-identifier">_init</span>(</span></span>);<br> <span class="hljs-comment">// 再提供工厂单例构造函数,用来标识该类为单例类</span><br> factory <span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">SingletonClass</span>.</span></span>shared<span class="hljs-constructor">Instance()</span> {<br> <span class="hljs-keyword">if</span> (_instance<span class="hljs-operator"> == </span>null) {<br> <span class="hljs-comment">// 调用私有构造函数创建实例,并赋值给静态变量</span><br> _instance = <span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">SingletonClass</span>.</span><span class="hljs-module"><span class="hljs-identifier">_init</span>(</span></span>);<br> <span class="hljs-comment">// 可以在此处设置参数默认值</span><br> <span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">_instance</span>.</span></span>params1 = <span class="hljs-character">'1'</span>;<br> }<br> return _instance;<br> }<br>}<br><br></code></pre></td></tr></table></figure><blockquote><p>说明:</p></blockquote><ol><li>单例需要在整个<code>APP</code>内存中保持只被创建一次,所以需要使用静态变量</li><li>为了标识某个类为单例类,增加可读性,所以建议使用统一格式或者统一关键字的有名构造函数,无名构造函数可以不提供</li><li>提供私有构造函数来初始化实例对象,防止其他库直接访问该初始化方法</li></ol><h4 id="三、使用单例进行通知"><a href="#三、使用单例进行通知" class="headerlink" title="三、使用单例进行通知"></a>三、使用单例进行通知</h4><figure class="highlight csharp"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><code class="hljs csharp"><br><span class="hljs-function">typedef <span class="hljs-keyword">void</span> <span class="hljs-title">NotiCallback</span><<span class="hljs-title">T</span>>(<span class="hljs-params"><span class="hljs-keyword">params</span></span>)</span>;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title">EventBus</span> {<br> <span class="hljs-comment">// 静态变量</span><br> <span class="hljs-keyword">static</span> EventBus _instance;<br> <span class="hljs-comment">// 默认无名构造方法</span><br> <span class="hljs-function">factory <span class="hljs-title">EventBus</span>(<span class="hljs-params"></span>)</span> {<br> <span class="hljs-keyword">return</span> EventBus.sharedInstance();<br> }<br> <span class="hljs-comment">// 私有构造方法</span><br> EventBus._init();<br> <span class="hljs-comment">// 单例对外提供的构造方法</span><br> factory EventBus.sharedInstance() {<br> <span class="hljs-keyword">if</span> (_instance == <span class="hljs-literal">null</span>) {<br> _instance = EventBus._init();<br> }<br> <span class="hljs-keyword">return</span> _instance;<br> }<br><br> <span class="hljs-comment">// 保存callback的参数</span><br> Map<String, NotiCallback> _notiMap = Map();<br><br> <span class="hljs-comment">// 对外提供添加,删除,触发的方法</span><br> <span class="hljs-comment">// 添加</span><br> <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">add</span><<span class="hljs-title">String</span>, <span class="hljs-title">NotiCallback</span>>(<span class="hljs-params">eventName, callback</span>)</span> {<br> <span class="hljs-keyword">if</span> (eventName == <span class="hljs-literal">null</span>) {<br> <span class="hljs-keyword">return</span>;<br> }<br> <span class="hljs-keyword">if</span> (eventName.length == <span class="hljs-number">0</span>) {<br> <span class="hljs-keyword">return</span>;<br> }<br> _notiMap[eventName] = callback;<br> }<br> <span class="hljs-comment">// 移除</span><br> <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">remove</span><<span class="hljs-title">String</span>, <span class="hljs-title">NotiCallback</span>>(<span class="hljs-params">eventName, callback</span>)</span> {<br> <span class="hljs-keyword">if</span> (eventName == <span class="hljs-literal">null</span>) {<br> <span class="hljs-keyword">return</span>;<br> }<br> <span class="hljs-keyword">if</span> (eventName.length == <span class="hljs-number">0</span>) {<br> <span class="hljs-keyword">return</span>;<br> }<br> _notiMap[eventName] = <span class="hljs-literal">null</span>;<br> }<br> <span class="hljs-comment">// 触发</span><br> <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">emit</span><<span class="hljs-title">String</span>, <span class="hljs-title">T</span>>(<span class="hljs-params">eventName, <span class="hljs-keyword">params</span></span>)</span> {<br> <span class="hljs-keyword">if</span> (eventName == <span class="hljs-literal">null</span>) {<br> <span class="hljs-keyword">return</span>;<br> }<br> <span class="hljs-keyword">if</span> (eventName.length == <span class="hljs-number">0</span>) {<br> <span class="hljs-keyword">return</span>;<br> }<br> NotiCallback callback = _notiMap[eventName];<br> callback(<span class="hljs-keyword">params</span>);<br> }<br>}<br><br></code></pre></td></tr></table></figure><p>使用<code>callback</code>进行传参,在单例中一对一保存<code>callback</code>,如果是一对多的场景,可在单例中保存<code>list</code>数据</p>]]></content>
<categories>
<category>flutter</category>
</categories>
<tags>
<tag>flutter</tag>
<tag>学习日记</tag>
<tag>单例</tag>
</tags>
</entry>
<entry>
<title>Flutter全局捕获报错信息</title>
<link href="/2020/03/26/Flutter%E5%85%A8%E5%B1%80%E6%8D%95%E8%8E%B7%E6%8A%A5%E9%94%99%E4%BF%A1%E6%81%AF/"/>
<url>/2020/03/26/Flutter%E5%85%A8%E5%B1%80%E6%8D%95%E8%8E%B7%E6%8A%A5%E9%94%99%E4%BF%A1%E6%81%AF/</url>
<content type="html"><![CDATA[<h4 id="一、系统方法"><a href="#一、系统方法" class="headerlink" title="一、系统方法"></a>一、系统方法</h4><figure class="highlight scala"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br></pre></td><td class="code"><pre><code class="hljs scala"><span class="hljs-keyword">import</span> <span class="hljs-symbol">'dart</span>:async';<br><span class="hljs-keyword">import</span> <span class="hljs-symbol">'package</span>:demo_error/<span class="hljs-type">Page1</span>.dart';<br><span class="hljs-keyword">import</span> <span class="hljs-symbol">'package</span>:flutter/material.dart';<br><br><span class="hljs-type">GlobalKey</span><<span class="hljs-type">NavigatorState</span>> navigatorKey = <span class="hljs-type">GlobalKey</span><<span class="hljs-type">NavigatorState</span>>();<br><br>void main() {<br> _reportError(dynamic error, dynamic stackTrace) async {<br> showDeleteConfirmDialog1(error.toString() + stackTrace.toString());<br> }<br><br> <span class="hljs-comment">// 捕获同步代码的报错</span><br> <span class="hljs-type">FlutterError</span>.onError = (<span class="hljs-type">FlutterErrorDetails</span> details) async {<br> await _reportError(details.exception, details.stack);<br> };<br> runZoned(() async {<br> runApp(<span class="hljs-type">MyApp</span>());<br> }, onError: (error, stackTrace) async {<br> <span class="hljs-comment">// 捕获异步代码的报错</span><br> await _reportError(error, stackTrace);<br> });<br>}<br><br><span class="hljs-comment">// 弹出对话框</span><br><span class="hljs-type">Future</span><bool> showDeleteConfirmDialog1(<span class="hljs-type">String</span> content) {<br> <span class="hljs-keyword">return</span> showDialog<bool>(<br> context: navigatorKey.currentState.overlay.context,<br> builder: (context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">AlertDialog</span>(<br> title: <span class="hljs-type">Text</span>(<span class="hljs-string">"提示"</span>),<br> content: <span class="hljs-type">Text</span>(content),<br> actions: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">FlatButton</span>(<br> child: <span class="hljs-type">Text</span>(<span class="hljs-string">"确定"</span>),<br> onPressed: () {<br> <span class="hljs-type">Navigator</span>.of(context).pop();<br> },<br> ),<br> ],<br> );<br> },<br> );<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">MaterialApp</span>(<br> navigatorKey: navigatorKey,<br> title: <span class="hljs-symbol">'Erro</span>r',<br> theme: <span class="hljs-type">ThemeData</span>(<br> primarySwatch: <span class="hljs-type">Colors</span>.blue,<br> ),<br> home: <span class="hljs-type">MyHomePage</span>(title: '主页'),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyHomePage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> <span class="hljs-type">MyHomePage</span>({<span class="hljs-type">Key</span> key, <span class="hljs-keyword">this</span>.title}) : <span class="hljs-keyword">super</span>(key: key);<br> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> title;<br><br> <span class="hljs-meta">@override</span><br> _MyHomePageState createState() => _MyHomePageState();<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_MyHomePageState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<MyHomePage></span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(widget.title),<br> ),<br> body: <span class="hljs-type">Center</span>(<br> child: <span class="hljs-type">Column</span>(<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">RaisedButton</span>(<br> child: <span class="hljs-type">Text</span>('同步数组越界'),<br> onPressed: () {<br> <span class="hljs-type">List</span><int> a = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>];<br> int i = a[<span class="hljs-number">2</span>];<br> print(i);<br> },<br> ),<br> <span class="hljs-type">RaisedButton</span>(<br> child: <span class="hljs-type">Text</span>('异步数组越界'),<br> onPressed: () {<br> <span class="hljs-type">Future</span>.delayed(<span class="hljs-type">Duration</span>(seconds: <span class="hljs-number">2</span>)).then((value) {<br> <span class="hljs-type">List</span><int> a = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>];<br> int i = a[<span class="hljs-number">2</span>];<br> print(i);<br> });<br> },<br> ),<br> ],<br> ),<br> ),<br> );<br> }<br>}<br><br></code></pre></td></tr></table></figure><ol><li><code>main()</code>中两个方法分别对应同步的报错和异步的报错</li><li>为了将报错信息使用弹窗弹出,所以用<code>GlobalKey</code>来获取全局的<code>context</code></li><li>如果直接运行<code>flutter</code>工程,从<code>main()</code>启动,是无法看到效果的,必须使用<code>Xcode</code>或者<code>Android Studio</code>运行<code>ios</code>或<code>android</code>目录下的原生工程才能看到效果,具体原因暂不清楚</li></ol><h4 id="二、第三方插件catcher"><a href="#二、第三方插件catcher" class="headerlink" title="二、第三方插件catcher"></a>二、第三方插件<code>catcher</code></h4><p><a href="https://pub.dev/packages/catcher"><code>https://pub.dev/packages/catcher</code></a></p><p>同样需要运行原生工程才有效果,此插件底层用的仍是上面的官方方法,在外层进行了封装,封装了其他非弹窗形式的提醒效果</p>]]></content>
<categories>
<category>flutter</category>
</categories>
<tags>
<tag>flutter</tag>
<tag>捕获报错</tag>
</tags>
</entry>
<entry>
<title>Flutter中Redux框架使用简介</title>
<link href="/2020/03/26/Flutter%E4%B8%ADRedux%E6%A1%86%E6%9E%B6%E4%BD%BF%E7%94%A8%E7%AE%80%E4%BB%8B/"/>
<url>/2020/03/26/Flutter%E4%B8%ADRedux%E6%A1%86%E6%9E%B6%E4%BD%BF%E7%94%A8%E7%AE%80%E4%BB%8B/</url>
<content type="html"><![CDATA[<blockquote><p><code>Redux</code>是一种状态容器,提供一种状态管理的机制。在<code>React-Native</code>和<code>Flutter</code>中,都有对应的集成方法。</p></blockquote><blockquote><p>在<code>Flutter</code>中,官方提供了基础的状态管理的控件<code>InheritedWidget</code>,所以本质上<code>flutter_redux</code>只是对<code>InheritedWidget</code>的封装</p></blockquote><h4 id="一、集成"><a href="#一、集成" class="headerlink" title="一、集成"></a>一、集成</h4><p><code>pubspec.yaml</code>中引入需要引入对应的插件包,具体最新的版本,需要在<a href="https://pub.dev/">官方网站</a>站查询</p><figure class="highlight apache"><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><code class="hljs apache"><span class="hljs-attribute">dependencies</span>:<br> <span class="hljs-attribute">flutter</span>:<br> <span class="hljs-attribute">sdk</span>: flutter<br><br> <span class="hljs-attribute">redux</span>: ^<span class="hljs-number">4</span>.<span class="hljs-number">0</span>.<span class="hljs-number">0</span><br> <span class="hljs-attribute">flutter_redux</span>: ^<span class="hljs-number">0</span>.<span class="hljs-number">6</span>.<span class="hljs-number">0</span><br> <span class="hljs-attribute">redux_thunk</span>: ^<span class="hljs-number">0</span>.<span class="hljs-number">3</span>.<span class="hljs-number">0</span><br></code></pre></td></tr></table></figure><p>调用<code>flutter packages get</code>命令加载插件</p><h4 id="二、简单介绍"><a href="#二、简单介绍" class="headerlink" title="二、简单介绍"></a>二、简单介绍</h4><ul><li><code>Store</code></li><li><code>Reducer</code></li><li><code>State</code></li></ul><ol><li><p><code>Store</code>负责保存各种方法和属性的实例,其中主要参数<code>reducer</code>、<code>initialState</code>和<code>middleware</code></p></li><li><p>其中<code>reducer</code>是绑定数据和操作的类,包含两个属性,<code>state</code>和<code>action</code>,需要在<code>reducer</code>中判断每个<code>action</code>具体对应到什么参数操作</p></li><li><p><code>Store</code>实例创建完成后,需要加入到<code>widgets</code>树中去,需要使用<code>StoreProvider</code>类,<code>Store</code>实例必须要加入到<code>widgets</code>树的最顶层,所以,<code>StoreProvider</code>要比整个<code>APP</code>的入口<code>MaterialApp</code>更高,仅次于<code>runApp</code>的方法</p></li><li><p>在任意一层<code>widget</code>中使用快捷的<code>of</code>方法,即可从<code>context</code>中获取到<code>Store</code>实例对象</p></li><li><p><code>redux_thunk</code>插件提供从接口请求数据的绑定操作,将<code>thunkMiddleware</code>值传入<code>Store</code>的<code>middleware</code>参数,通过<code>store.dispatch</code>方法可以调用绑定的数据请求的方法,数据请求的方法需要有返回值类型<code>ThunkAction<State></code>,此类型为定义的别名,</p><figure class="highlight elm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs elm">typedef dynamic <span class="hljs-type">ThunkAction</span><<span class="hljs-type">State</span>>(<span class="hljs-type">Store</span><<span class="hljs-type">State</span>> store);<br></code></pre></td></tr></table></figure><p>所以直接<code>Store</code>对象,并在方法中实现具体的请求参数等逻辑</p></li><li><p><code>dispatch</code>触发数据请求后,还需要继续执行<code>dispatch</code>操作,继续触发<code>action</code>,通过判断<code>action</code>类型来执行具体的数据保存操作,全部执行完成后,数据会保存在<code>State</code>中,此时<code>redux</code>会触发数据变化的通知,重构<code>StoreConnector</code>中<code>builder</code>的实现</p></li></ol><h4 id="三、示例代码"><a href="#三、示例代码" class="headerlink" title="三、示例代码"></a>三、示例代码</h4><p><a href="https://github.com/AnderGH/flutter_redux_demo/blob/master/demo_redux/lib/main.dart"><code>https://github.com/AnderGH/flutter_redux_demo/blob/master/demo_redux/lib/main.dart</code></a></p>]]></content>
<categories>
<category>flutter</category>
</categories>
<tags>
<tag>flutter</tag>
<tag>Redux</tag>
</tags>
</entry>
<entry>
<title>Flutter学习日记-log6</title>
<link href="/2020/03/13/Flutter%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log6/"/>
<url>/2020/03/13/Flutter%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log6/</url>
<content type="html"><![CDATA[<blockquote><p><a href="https://flutterchina.club/get-started/install/"><em>Flutter中文网</em></a></p></blockquote><hr><h2 id="日志随笔"><a href="#日志随笔" class="headerlink" title="日志随笔"></a>日志随笔</h2><h3 id="一、跨组件状态共享(Provider)"><a href="#一、跨组件状态共享(Provider)" class="headerlink" title="一、跨组件状态共享(Provider)"></a>一、跨组件状态共享(Provider)</h3><p>其实就是对普通写法的一种封装,采用泛型进行封装,提供一个继承于<code>Widget</code>的组件,将保存共享数据的入口和读取的入口封装在里面,对外提供统一的方法<br>此外,还封装了一个修改的方法,修改的方法在数据修改后需要通知主<code>Widget</code>进行刷新,我尝试采用<code>callback</code>回调进行通知,失败,因为静态方法无法访问成员变量,所以无法进行回调<br><code>demo</code>中采用了继承<code>Listenable</code>的监听,当参数发生变化时,通知所有监听的地方,但是这样需要封装一个<code>model</code>的类出来,用来发出通知</p><p>文档中代码报错,无法运行,关于<code>Listenable</code>监听的逻辑以后再研究</p><figure class="highlight scala"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br></pre></td><td class="code"><pre><code class="hljs scala"><span class="hljs-keyword">import</span> <span class="hljs-symbol">'dart</span>:ffi';<br><br><span class="hljs-keyword">import</span> <span class="hljs-symbol">'package</span>:flutter/material.dart';<br><br>void main() => runApp(<span class="hljs-type">MyApp</span>());<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">MaterialApp</span>(<br> title: <span class="hljs-symbol">'provide</span>r',<br> theme: <span class="hljs-type">ThemeData</span>(<br> primarySwatch: <span class="hljs-type">Colors</span>.blue,<br> ),<br> home: <span class="hljs-type">MyHomePage</span>(title: '主页'),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyHomePage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> <span class="hljs-type">MyHomePage</span>({<span class="hljs-type">Key</span> key, <span class="hljs-keyword">this</span>.title}) : <span class="hljs-keyword">super</span>(key: key);<br> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> title;<br><br> <span class="hljs-meta">@override</span><br> _MyHomePageState createState() => _MyHomePageState();<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_MyHomePageState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<MyHomePage></span> </span>{<br> <span class="hljs-keyword">var</span> _counter = <span class="hljs-number">0</span>;<br><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(widget.title),<br> ),<br> body: <span class="hljs-type">Provider</span>(<br> data: _counter,<br> child: <span class="hljs-type">Center</span>(<br> child: <span class="hljs-type">Column</span>(<br> mainAxisAlignment: <span class="hljs-type">MainAxisAlignment</span>.center,<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">Builder</span>(builder: (builder) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Text</span>(<br> <span class="hljs-comment">// 普通类型可以直接使用</span><br> <span class="hljs-type">Provider</span>.of(builder).toString(),<br> );<br> }),<br> <span class="hljs-type">Builder</span>(builder: (builder) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">RaisedButton</span>(<br> onPressed: () {<br> <span class="hljs-comment">// 直接修改参数,然后通知状态变化</span><br> _counter++;<br> setState(() {});<br> },<br> child: <span class="hljs-type">Icon</span>(<span class="hljs-type">Icons</span>.add),<br> );<br> }),<br> ],<br> ),<br> ),<br> changedCallBack: () {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> },<br> ),<br> );<br> }<br>}<br><br><span class="hljs-comment">// 声明一个通知类,里面包含一个通知的方法</span><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProviderChangeedNotifier</span> <span class="hljs-title">implements</span> <span class="hljs-title">Listenable</span> </span>{<br> void notifyListeners() {<br> <span class="hljs-comment">// 通知所有监听器,触发回调</span><br> print(<span class="hljs-symbol">'notifyListener</span>s');<br> }<br><br> <span class="hljs-meta">@override</span><br> void addListener(listener) {<br> print(<span class="hljs-symbol">'addListene</span>r');<br> }<br><br> <span class="hljs-meta">@override</span><br> void removeListener(listener) {<br> print(<span class="hljs-symbol">'removeListene</span>r');<br> }<br>}<br><br><span class="hljs-comment">// 继承通知类,负责保存数据参数和修改后进行通知</span><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProviderModel</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ProviderChangeedNotifier</span> </span>{<br> <span class="hljs-keyword">var</span> data = <span class="hljs-number">0</span>;<br><br> change<<span class="hljs-type">T</span> <span class="hljs-keyword">extends</span> <span class="hljs-type">ProviderChangeedNotifier</span>>(params) {<br> data = params;<br> notifyListeners();<br> }<br>}<br><br>typedef <span class="hljs-type">ProviderSharedDataChangedCallBack</span> = <span class="hljs-type">Future</span> <span class="hljs-type">Function</span>();<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Provider<T</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ProviderChangeedNotifier></span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> <span class="hljs-type">Provider</span>({<br> <span class="hljs-type">Key</span> key,<br> <span class="hljs-meta">@required</span> <span class="hljs-keyword">this</span>.data,<br> <span class="hljs-keyword">this</span>.child,<br> <span class="hljs-meta">@required</span> <span class="hljs-keyword">this</span>.changedCallBack,<br> }) : <span class="hljs-keyword">super</span>(key: key);<br> <span class="hljs-keyword">final</span> <span class="hljs-type">T</span> data;<br> <span class="hljs-keyword">final</span> <span class="hljs-type">Widget</span> child;<br> <span class="hljs-keyword">final</span> <span class="hljs-type">ProviderSharedDataChangedCallBack</span> changedCallBack;<br><br> <span class="hljs-meta">@override</span><br> _ProviderState createState() => _ProviderState();<br><br> <span class="hljs-comment">// 获取共享参数的方法</span><br> static <span class="hljs-type">T</span> of<<span class="hljs-type">T</span> <span class="hljs-keyword">extends</span> <span class="hljs-type">ProviderChangeedNotifier</span>>(context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">SharedData</span>.of(context).data;<br> }<br><br> <span class="hljs-comment">// 修改共享参数的方法</span><br> static void changeSharedData(data) {<br> <span class="hljs-comment">// 此处无法调用changedCallBack属性进行回调操作</span><br> <span class="hljs-comment">// changedCallBack();</span><br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_ProviderState<T</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ProviderChangeedNotifier></span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<Provider<T>></span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">SharedData</span>(<br> data: widget.data,<br> child: widget.child,<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SharedData<T</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ProviderChangeedNotifier></span> <span class="hljs-keyword">extends</span> <span class="hljs-title">InheritedWidget</span> </span>{<br> <span class="hljs-type">SharedData</span>({<br> <span class="hljs-type">Key</span> key,<br> <span class="hljs-meta">@required</span> <span class="hljs-keyword">this</span>.data,<br> <span class="hljs-type">Widget</span> child,<br> }) : <span class="hljs-keyword">super</span>(key: key, child: child);<br> <span class="hljs-keyword">final</span> <span class="hljs-type">T</span> data;<br><br> <span class="hljs-meta">@override</span><br> bool updateShouldNotify(<span class="hljs-type">SharedData</span> oldWidget) {<br> <span class="hljs-keyword">if</span> (oldWidget.data == data) {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br> }<br> }<br><br> <span class="hljs-comment">// 获取共享组件的方法</span><br> static <span class="hljs-type">SharedData</span> of(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> context.dependOnInheritedWidgetOfExactType();<br> }<br>}<br><br></code></pre></td></tr></table></figure><h3 id="二、颜色和主题"><a href="#二、颜色和主题" class="headerlink" title="二、颜色和主题"></a>二、颜色和主题</h3><h3 id="三、异步UI更新(FutureBuilder、StreamBuilder)"><a href="#三、异步UI更新(FutureBuilder、StreamBuilder)" class="headerlink" title="三、异步UI更新(FutureBuilder、StreamBuilder)"></a>三、异步UI更新(FutureBuilder、StreamBuilder)</h3><h3 id="四、对话框"><a href="#四、对话框" class="headerlink" title="四、对话框"></a>四、对话框</h3><p><span style="color: lightgray;"><em>未完待续</em></span></p>]]></content>
<categories>
<category>flutter</category>
</categories>
<tags>
<tag>flutter</tag>
<tag>学习日记</tag>
</tags>
</entry>
<entry>
<title>Flutter学习日记-log5</title>
<link href="/2020/03/12/Flutter%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log5/"/>
<url>/2020/03/12/Flutter%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log5/</url>
<content type="html"><![CDATA[<blockquote><p><a href="https://flutterchina.club/get-started/install/"><em>Flutter中文网</em></a></p></blockquote><hr><h2 id="日志随笔"><a href="#日志随笔" class="headerlink" title="日志随笔"></a>日志随笔</h2><h3 id="一、复习"><a href="#一、复习" class="headerlink" title="一、复习"></a>一、复习</h3><ul><li><code>Scrollbar</code>添加通知<code>NotificationListener</code>监听后,应该<code>return false;</code>如果返回的是<code>true</code>,那么<code>Scrollbar</code>会消失</li></ul><h3 id="二、功能型组件"><a href="#二、功能型组件" class="headerlink" title="二、功能型组件"></a>二、功能型组件</h3><h4 id="1、导航返回拦截"><a href="#1、导航返回拦截" class="headerlink" title="1、导航返回拦截"></a>1、导航返回拦截</h4><p><code>iOS</code>应该不需要</p><h4 id="2、数据共享(InheritedWidget)"><a href="#2、数据共享(InheritedWidget)" class="headerlink" title="2、数据共享(InheritedWidget)"></a>2、数据共享(InheritedWidget)</h4><p><code>InheritedWidget</code>提供了一种数据在<code>widget</code>树中从上到下传递、共享的方式,比如我们在应用的根<code>widget</code>中通过<code>InheritedWidget</code>共享了一个数据,那么我们便可以在任意子<code>widget</code>中来获取该共享的数据</p><p><code>InheritedWidget</code>和<code>React</code>中的<code>context</code>功能类似,和逐级传递数据相比,它们能实现组件跨级传递数据</p><figure class="highlight scala"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br></pre></td><td class="code"><pre><code class="hljs scala"><span class="hljs-keyword">import</span> <span class="hljs-symbol">'dart</span>:ffi';<br><span class="hljs-keyword">import</span> <span class="hljs-symbol">'dart</span>:ui';<br><br><span class="hljs-keyword">import</span> <span class="hljs-symbol">'package</span>:flutter/material.dart';<br><br>void main() => runApp(<span class="hljs-type">MyApp</span>());<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">MaterialApp</span>(<br> title: <span class="hljs-symbol">'InheritedWidge</span>t',<br> theme: <span class="hljs-type">ThemeData</span>(<br> primarySwatch: <span class="hljs-type">Colors</span>.blue,<br> ),<br> home: <span class="hljs-type">MyHomePage</span>(title: '主页'),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyHomePage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> <span class="hljs-type">MyHomePage</span>({<span class="hljs-type">Key</span> key, <span class="hljs-keyword">this</span>.title}) : <span class="hljs-keyword">super</span>(key: key);<br> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> title;<br><br> <span class="hljs-meta">@override</span><br> _MyHomePageState createState() => _MyHomePageState();<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_MyHomePageState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<MyHomePage></span> </span>{<br> int number = <span class="hljs-number">0</span>;<br><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(widget.title),<br> ),<br> body: <span class="hljs-type">Center</span>(<br> child: <span class="hljs-type">Column</span>(<br> mainAxisAlignment: <span class="hljs-type">MainAxisAlignment</span>.center,<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">ShareData</span>(<br> params: number.toString(),<br> child: <span class="hljs-type">TextWidget</span>(),<br> ),<br> <span class="hljs-type">RaisedButton</span>(<br> onPressed: () {<br> number++;<br> setState(() {});<br> },<br> child: <span class="hljs-type">Icon</span>(<span class="hljs-type">Icons</span>.add),<br> ),<br> ],<br> ),<br> ),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ShareData</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">InheritedWidget</span> </span>{<br> <span class="hljs-type">ShareData</span>({<br> <span class="hljs-type">Key</span> key,<br> <span class="hljs-meta">@required</span> <span class="hljs-keyword">this</span>.params,<br> <span class="hljs-type">Widget</span> child,<br> }) : <span class="hljs-keyword">super</span>(key: key, child: child);<br> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> params;<br><br> <span class="hljs-meta">@override</span><br> bool updateShouldNotify(<span class="hljs-type">ShareData</span> oldWidget) {<br> debugPrint(<span class="hljs-symbol">'updateShouldNotif</span>y');<br> <span class="hljs-keyword">if</span> (oldWidget.params != params) {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br> }<br> }<br><br> static <span class="hljs-type">ShareData</span> getSharedData(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> context.dependOnInheritedWidgetOfExactType();<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TextWidget</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> _TextWidgetState createState() => _TextWidgetState();<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_TextWidgetState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<TextWidget></span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Text</span>(<br> <span class="hljs-type">ShareData</span>.getSharedData(context).params.toString(),<br> style: <span class="hljs-type">TextStyle</span>(<br> fontSize: <span class="hljs-number">30</span>,<br> ),<br> );<br> }<br><br> <span class="hljs-meta">@override</span><br> void didChangeDependencies() {<br> <span class="hljs-keyword">super</span>.didChangeDependencies();<br> debugPrint(<span class="hljs-symbol">'didChangeDependencie</span>s');<br> }<br>}<br><br></code></pre></td></tr></table></figure><p><span style="color: lightgray;"><em>未完待续</em></span></p>]]></content>
<categories>
<category>flutter</category>
</categories>
<tags>
<tag>flutter</tag>
<tag>学习日记</tag>
</tags>
</entry>
<entry>
<title>Flutter学习日记-log4</title>
<link href="/2020/03/11/Flutter%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log4/"/>
<url>/2020/03/11/Flutter%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log4/</url>
<content type="html"><![CDATA[<blockquote><p><a href="https://flutterchina.club/get-started/install/"><em>Flutter中文网</em></a></p></blockquote><hr><h2 id="日志随笔"><a href="#日志随笔" class="headerlink" title="日志随笔"></a>日志随笔</h2><h3 id="一、复习"><a href="#一、复习" class="headerlink" title="一、复习"></a>一、复习</h3><ul><li>如果使用<code>Navigator.push</code>方法传参,那么接收回调参数时,可以使用确定类型例如<code>String</code>等接收,也可以使用<code>var</code>接收,如果使用的命名路由传参,那么只能使用<code>var</code>接收回调参数,否则会报错</li><li><code>=></code>代表调用无参数的函数,并获取返回值</li></ul><figure class="highlight javascript"><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></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-string">'HomePage'</span>: <span class="hljs-function">(<span class="hljs-params">context</span>) =></span> HomePage(),<br><span class="hljs-comment">// 另外写法</span><br><span class="hljs-string">'HomePage'</span>: (context) {<br> <span class="hljs-keyword">return</span> HomePage();<br>},<br><br>_HomePageState createState() => _HomePageState();<br><span class="hljs-comment">// 另外写法</span><br>State<StatefulWidget> <span class="hljs-function"><span class="hljs-title">createState</span>(<span class="hljs-params"></span>)</span> {<br> <span class="hljs-keyword">return</span> _HomePageState();<br>}<br></code></pre></td></tr></table></figure><h3 id="二、容器类组件"><a href="#二、容器类组件" class="headerlink" title="二、容器类组件"></a>二、容器类组件</h3><ul><li>布局类组件需要一个<code>widget</code>数组<code>(children)</code>,直接或间接继承自(或包含)<code>MultiChildRenderObjectWidget</code>;而容器类组件只需要一个子<code>Widget</code> <code>(child)</code>,直接或间接继承自(或包含)<code>SingleChildRenderObjectWidget</code></li><li>布局类组件是按照一定的排列方式来对其子<code>Widget</code>进行排列;而容器类组件一般只是包装其子<code>Widget</code>,对其添加一些修饰(补白或背景色等)、变换(旋转或剪裁等)、或限制(大小等)</li></ul><h4 id="1、填充(Padding)"><a href="#1、填充(Padding)" class="headerlink" title="1、填充(Padding)"></a>1、填充(Padding)</h4><p><code>EdgeInsets</code>属性</p><ul><li><code>fromLTRB(double left, double top, double right, double bottom)</code>:分别指定四个方向的填充</li><li><code>all(double value)</code>: 所有方向均使用相同数值的填充</li><li><code>only({left, top, right ,bottom })</code>:可以设置具体某个方向的填充(可以同时指定多个方向)</li><li><code>symmetric({ vertical, horizontal })</code>:用于设置对称方向的填充,<code>vertical</code>指<code>top</code>和<code>bottom</code>,<code>horizontal</code>指<code>left</code>和<code>right</code></li></ul><h4 id="2、尺寸限制类容器"><a href="#2、尺寸限制类容器" class="headerlink" title="2、尺寸限制类容器"></a>2、尺寸限制类容器</h4><ul><li><code>ConstrainedBox</code>用于对子组件添加额外的约束</li><li><code>SizedBox</code>用于给子元素指定固定的宽高</li><li><code>UnconstrainedBox</code>不会对子组件产生任何限制,它允许其子组件按照其本身大小绘制,例如去除父级限制</li></ul><h4 id="3、装饰容器"><a href="#3、装饰容器" class="headerlink" title="3、装饰容器"></a>3、装饰容器</h4><h5 id="1-DecoratedBox"><a href="#1-DecoratedBox" class="headerlink" title="1. DecoratedBox"></a>1. DecoratedBox</h5><ul><li><code>decoration</code>:代表将要绘制的装饰,它的类型为<code>Decoration</code>。<code>Decoration</code>是一个抽象类。</li><li><code>position</code>:此属性决定在哪里绘制<code>Decoration</code>,它接收<code>DecorationPosition</code>的枚举类型,该枚举类有两个值:<ul><li><code>background</code>:在子组件之后绘制,即背景装饰</li><li><code>foreground</code>:在子组件之上绘制,即前景</li></ul></li></ul><h5 id="2-BoxDecoration"><a href="#2-BoxDecoration" class="headerlink" title="2. BoxDecoration"></a>2. BoxDecoration</h5><blockquote><p>通常会直接使用<code>BoxDecoration</code>类,它是一个<code>Decoration</code>的子类</p></blockquote><h4 id="4、变换(Transform)"><a href="#4、变换(Transform)" class="headerlink" title="4、变换(Transform)"></a>4、变换(Transform)</h4><p><code>Transform</code>变换是应用在绘制阶段,而并不是应用在布局阶段,所以无论对子组件应用何种变化,其占用空间的大小和在屏幕上的位置都是固定不变的,因为这些是在布局阶段就确定的</p><h5 id="1-平移"><a href="#1-平移" class="headerlink" title="1. 平移"></a>1. 平移</h5><ul><li><code>Transform.translate</code>接收一个<code>offset</code>参数,可以在绘制时沿<code>x、y</code>轴对子组件平移指定的距离</li></ul><h5 id="2-旋转"><a href="#2-旋转" class="headerlink" title="2. 旋转"></a>2. 旋转</h5><ul><li><code>Transform.rotate</code>可以对子组件进行旋转变换</li></ul><h5 id="3-缩放"><a href="#3-缩放" class="headerlink" title="3. 缩放"></a>3. 缩放</h5><ul><li>Transform.scale可以对子组件进行缩小或放大</li></ul><h4 id="5、Container"><a href="#5、Container" class="headerlink" title="5、Container"></a>5、Container</h4><p><code>Container</code>是一个组合类容器,它本身不对应具体的<code>RenderObject</code>,它是<code>DecoratedBox、ConstrainedBox、Transform、Padding、Align</code>等组件组合的一个多功能容器,所以只需通过一个<code>Container</code>组件可以实现同时需要装饰、变换、限制的场景</p><h4 id="6、Scaffold、TabBar、底部导航"><a href="#6、Scaffold、TabBar、底部导航" class="headerlink" title="6、Scaffold、TabBar、底部导航"></a>6、Scaffold、TabBar、底部导航</h4><h5 id="1-Scaffold"><a href="#1-Scaffold" class="headerlink" title="1. Scaffold"></a>1. Scaffold</h5><p><code>Scaffold</code>是一个路由页的骨架,包含导航栏、抽屉菜单以及底部<code>Tab</code>导航菜单等</p><h5 id="2-AppBar"><a href="#2-AppBar" class="headerlink" title="2. AppBar"></a>2. AppBar</h5><ul><li><code>AppBar</code>是一个<code>Material</code>风格的导航栏,可以设置导航栏标题、导航栏菜单、导航栏底部的<code>Tab</code>标题等</li></ul><h5 id="3-TabBar"><a href="#3-TabBar" class="headerlink" title="3. TabBar"></a>3. TabBar</h5><ul><li><code>bottom</code>属性来添加一个导航栏底部<code>Tab</code>按钮组</li></ul><h5 id="4-TabBarView"><a href="#4-TabBarView" class="headerlink" title="4. TabBarView"></a>4. TabBarView</h5><ul><li><code>TabBar</code>我们只能生成一个静态的菜单,我们需要通过<code>TabController</code>去监听<code>Tab</code>菜单的切换去切换<code>Tab</code>页</li></ul><h5 id="5-抽屉菜单Drawer"><a href="#5-抽屉菜单Drawer" class="headerlink" title="5. 抽屉菜单Drawer"></a>5. 抽屉菜单Drawer</h5><ul><li><code>Scaffold</code>的<code>drawer</code>和<code>endDrawer</code>属性可以分别接受一个<code>Widget</code>来作为页面的左、右抽屉菜单</li></ul><h5 id="6-FloatingActionButton"><a href="#6-FloatingActionButton" class="headerlink" title="6. FloatingActionButton"></a>6. FloatingActionButton</h5><ul><li><code>FloatingActionButton</code>是<code>Material</code>设计规范中的一种特殊<code>Button</code>,通常悬浮在页面的某一个位置作为某种常用动作的快捷入口</li></ul><h4 id="7、剪裁(Clip)"><a href="#7、剪裁(Clip)" class="headerlink" title="7、剪裁(Clip)"></a>7、剪裁(Clip)</h4><ul><li><code>CustomClipper</code>自定义剪裁区域</li></ul><h3 id="三、可滚动组件"><a href="#三、可滚动组件" class="headerlink" title="三、可滚动组件"></a>三、可滚动组件</h3><ul><li>当组件内容超过当前显示视口<code>ViewPort</code>时,如果没有特殊处理,<code>Flutter</code>则会提示<code>Overflow</code>错误</li><li><code>Flutter</code>提供了多种可滚动组件用于显示列表和长布局。可滚动组件都直接或间接包含一个<code>Scrollable</code>组件</li></ul><h4 id="1、简介"><a href="#1、简介" class="headerlink" title="1、简介"></a>1、简介</h4><ul><li><code>axisDirection</code>:滚动方向。</li><li><code>physics</code>:此属性接受一个<code>ScrollPhysics</code>类型的对象,它决定可滚动组件如何响应用户操作,比如用户滑动完抬起手指后,继续执行动画;或者滑动到边界时,如何显示。默认情况下,<code>Flutter</code>会根据具体平台分别使用不同的<code>ScrollPhysics</code>对象,应用不同的显示效果,如当滑动到边界时,继续拖动的话,在<code>iOS</code>上会出现弹性效果,而在<code>Android</code>上会出现微光效果。如果你想在所有平台下使用同一种效果,可以显式指定一个固定的<code>ScrollPhysics</code>,可以直接使用:<ul><li><code>ClampingScrollPhysics</code>:Android下微光效果。</li><li><code>BouncingScrollPhysics</code>:iOS下弹性效果。</li></ul></li><li><code>controller</code>:此属性接受一个<code>ScrollController</code>对象。<code>ScrollController</code>的主要作用是控制滚动位置和监听滚动事件。默认情况下,<code>Widget</code>树中会有一个默认的<code>PrimaryScrollController</code>,如果子树中的可滚动组件没有显式的指定<code>controller</code>,并且<code>primary</code>属性值为<code>true</code>时(默认就为<code>true</code>),可滚动组件会使用这个默认的<code>PrimaryScrollController</code>。这种机制带来的好处是父组件可以控制子树中可滚动组件的滚动行为,例如,<code>Scaffol</code>d正是使用这种机制在<code>iOS</code>中实现了点击导航栏回到顶部的功能。我们将在本章后面“滚动控制”一节详细介绍<code>ScrollController</code>。</li></ul><h5 id="1-Scrollbar"><a href="#1-Scrollbar" class="headerlink" title="1. Scrollbar"></a>1. Scrollbar</h5><ul><li><code>Scrollbar</code>是滚动指示器(滚动条),如果要给可滚动组件添加滚动条,只需将<code>Scrollbar</code>作为可滚动组件的任意一个父级组件即可</li><li><code>CupertinoScrollbar</code>如果你使用的是<code>Scrollbar</code>,那么在<code>iOS</code>平台它会自动切换为<code>CupertinoScrollbar</code></li></ul><h5 id="2-ViewPort视口"><a href="#2-ViewPort视口" class="headerlink" title="2. ViewPort视口"></a>2. ViewPort视口</h5><ul><li>指一个<code>Widget</code>的实际显示区域</li></ul><h5 id="3-基于Sliver的延迟构建"><a href="#3-基于Sliver的延迟构建" class="headerlink" title="3. 基于Sliver的延迟构建"></a>3. 基于Sliver的延迟构建</h5><ul><li><code>Flutter</code>中提出一个<code>Sliver</code>(中文为“薄片”的意思)概念,如果一个可滚动组件支持<code>Sliver</code>模型,那么该滚动可以将子组件分成好多个“薄片”<code>(Sliver)</code>,只有当<code>Sliver</code>出现在视口中时才会去构建它,这种模型也称为“基于<code>Sliver</code>的延迟构建模型”</li></ul><h4 id="2、SingleChildScrollView"><a href="#2、SingleChildScrollView" class="headerlink" title="2、SingleChildScrollView"></a>2、SingleChildScrollView</h4><ul><li>通常<code>SingleChildScrollView</code>只用在不会超过屏幕太多的场景,因为<code>SingleChildScrollView</code>不支持基于<code>Sliver</code>的延迟实例化模型</li></ul><h4 id="3、ListView"><a href="#3、ListView" class="headerlink" title="3、ListView"></a>3、ListView</h4><h5 id="1-默认构造函数"><a href="#1-默认构造函数" class="headerlink" title="1. 默认构造函数"></a>1. 默认构造函数</h5><p>默认构造函数有一个<code>children</code>参数。这种方式适合只有少量的子组件的情况,通过此方式创建的<code>ListView</code>和使用<code>SingleChildScrollView+Column</code>的方式没有本质的区别</p><h5 id="2-ListView-builder"><a href="#2-ListView-builder" class="headerlink" title="2. ListView.builder"></a>2. ListView.builder</h5><p><code>ListView.builder</code>适合列表项比较多(或者无限)的情况,因为只有当子组件真正显示的时候才会被创建,也就说通过该构造函数创建的<code>ListView</code>是支持基于<code>Sliver</code>的懒加载模型的</p><h5 id="3-ListView-separated"><a href="#3-ListView-separated" class="headerlink" title="3. ListView.separated"></a>3. ListView.separated</h5><p><code>ListView.separated</code>可以在生成的列表项之间添加一个分割组件,它比<code>ListView.builder</code>多了一个<code>separatorBuilder</code>参数,该参数是一个分割组件生成器</p><h5 id="4-添加固定列表头"><a href="#4-添加固定列表头" class="headerlink" title="4. 添加固定列表头"></a>4. 添加固定列表头</h5><p>以上示例代码如下:</p><figure class="highlight scala"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br></pre></td><td class="code"><pre><code class="hljs scala"><span class="hljs-keyword">import</span> <span class="hljs-symbol">'dart</span>:ffi';<br><span class="hljs-keyword">import</span> <span class="hljs-symbol">'dart</span>:io';<br><br><span class="hljs-keyword">import</span> <span class="hljs-symbol">'package</span>:flutter/material.dart';<br><span class="hljs-keyword">import</span> <span class="hljs-symbol">'package</span>:english_words/english_words.dart';<br><br>int _pageSize = <span class="hljs-number">20</span>;<br>int _pageIndex = <span class="hljs-number">1</span>;<br><span class="hljs-type">List</span><<span class="hljs-type">String</span>> _dataList = [];<br><br>void main() => runApp(<span class="hljs-type">MyApp</span>());<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">MaterialApp</span>(<br> title: '上拉下拉刷新',<br> theme: <span class="hljs-type">ThemeData</span>(<br> primarySwatch: <span class="hljs-type">Colors</span>.blue,<br> ),<br> home: <span class="hljs-type">HomePage</span>(),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HomePage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(<span class="hljs-symbol">'111</span>1'),<br> ),<br> body: <span class="hljs-type">InfiniteListView</span>(),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InfiniteListView</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> _InfiniteListViewState createState() {<br> <span class="hljs-keyword">return</span> _InfiniteListViewState();<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_InfiniteListViewState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<InfiniteListView></span> </span>{<br> <span class="hljs-comment">// 下拉刷新</span><br> void headerRefresh() {<br> _pageSize = <span class="hljs-number">20</span>;<br> _pageIndex = <span class="hljs-number">1</span>;<br> getData(<span class="hljs-literal">true</span>);<br> }<br><br> <span class="hljs-comment">// 上拉加载</span><br> void footerRefresh() {<br> _pageIndex++;<br> getData(<span class="hljs-literal">false</span>);<br> }<br><br> <span class="hljs-comment">// 获取数据</span><br> void getData(bool headerRefresh) {<br> <span class="hljs-comment">// 模拟接口请求2秒延迟</span><br> <span class="hljs-type">Future</span>.delayed(<br> <span class="hljs-type">Duration</span>(seconds: <span class="hljs-number">2</span>),<br> ).then((e) {<br> <span class="hljs-comment">// 模拟数据,第3页只返回5条</span><br> <span class="hljs-type">List</span><<span class="hljs-type">String</span>> currentPageList = [];<br> <span class="hljs-keyword">if</span> (_pageIndex < <span class="hljs-number">3</span>) {<br> <span class="hljs-keyword">for</span> (int i = ((_pageIndex - <span class="hljs-number">1</span>) * _pageSize);<br> i < (_pageIndex * _pageSize);<br> i++) {<br> currentPageList.add(i.toString());<br> }<br> } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (_pageIndex == <span class="hljs-number">3</span>) {<br> currentPageList.add('第三页数据');<br> }<br><br> <span class="hljs-keyword">if</span> (headerRefresh) {<br> _dataList = [];<br> } <span class="hljs-keyword">else</span> {<br> _dataList.removeLast();<br> }<br> _dataList.addAll(currentPageList);<br><br> <span class="hljs-keyword">if</span> (currentPageList.length == _pageSize) {<br> <span class="hljs-comment">// 数据满一页</span><br> _dataList.add('###<span class="hljs-type">FooterRefreshTag</span>###');<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-comment">// 数据不满一页</span><br> _dataList.add('###<span class="hljs-type">DataNone</span>###');<br> }<br><br> setState(() {});<br> });<br> }<br><br> <span class="hljs-meta">@override</span><br> void initState() {<br> <span class="hljs-keyword">super</span>.initState();<br><br> <span class="hljs-comment">// 初始值</span><br> _dataList.add('###<span class="hljs-type">HeaderRefreshTag</span>###');<br> }<br><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> double _cellHeight = <span class="hljs-number">50</span>;<br><br> <span class="hljs-keyword">return</span> <span class="hljs-type">Container</span>(<br> color: <span class="hljs-type">Colors</span>.grey[<span class="hljs-number">200</span>],<br> child: <span class="hljs-type">Scrollbar</span>(<br> child: <span class="hljs-type">ListView</span>.separated(<br> itemBuilder: (context, index) {<br> <span class="hljs-keyword">if</span> ((_dataList[index] == '###<span class="hljs-type">HeaderRefreshTag</span>###') ||<br> (_dataList[index] == '###<span class="hljs-type">FooterRefreshTag</span>###')) {<br> <span class="hljs-keyword">if</span> (_dataList[index] == '###<span class="hljs-type">HeaderRefreshTag</span>###') {<br> <span class="hljs-comment">// 下拉刷新</span><br> headerRefresh();<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-comment">// 上拉加载</span><br> footerRefresh();<br> }<br> <span class="hljs-comment">// 显示loading的样式</span><br> <span class="hljs-keyword">return</span> <span class="hljs-type">Container</span>(<br> height: _cellHeight,<br> child: <span class="hljs-type">Center</span>(<br> child: <span class="hljs-type">Container</span>(<br> width: <span class="hljs-number">25</span>,<br> height: <span class="hljs-number">25</span>,<br> child: <span class="hljs-type">CircularProgressIndicator</span>(<br> backgroundColor: <span class="hljs-type">Colors</span>.grey,<br> valueColor: <span class="hljs-type">AlwaysStoppedAnimation</span>(<span class="hljs-type">Colors</span>.blue),<br> ),<br> ),<br> ),<br> );<br> } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (_dataList[index] == '###<span class="hljs-type">DataNone</span>###') {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Container</span>(<br> height: _cellHeight,<br> child: <span class="hljs-type">Center</span>(<br> child: <span class="hljs-type">Text</span>(<br> '没有更多数据了',<br> style: <span class="hljs-type">TextStyle</span>(<br> color: <span class="hljs-type">Colors</span>.grey,<br> ),<br> ),<br> ),<br> );<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Container</span>(<br> color: <span class="hljs-type">Colors</span>.white,<br> height: _cellHeight,<br> <span class="hljs-comment">// 约束布局</span><br> child: <span class="hljs-type">Container</span>(<br> child: <span class="hljs-type">Flex</span>(<br> direction: <span class="hljs-type">Axis</span>.vertical,<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">Expanded</span>(<br> child: <span class="hljs-type">Container</span>(<br> width: double.infinity,<br> child: <span class="hljs-type">Padding</span>(<br> padding: <span class="hljs-type">EdgeInsets</span>.only(<br> left: <span class="hljs-number">16</span>,<br> top: <span class="hljs-number">4</span>,<br> right: <span class="hljs-number">8</span>,<br> ),<br> child: <span class="hljs-type">Text</span>(<br> '主标题' + index.toString(),<br> style: <span class="hljs-type">TextStyle</span>(<br> fontSize: <span class="hljs-number">20</span>,<br> ),<br> ),<br> ),<br> ),<br> flex: <span class="hljs-number">3</span>,<br> ),<br> <span class="hljs-type">Expanded</span>(<br> child: <span class="hljs-type">Container</span>(<br> width: double.infinity,<br> child: <span class="hljs-type">Padding</span>(<br> padding: <span class="hljs-type">EdgeInsets</span>.only(<br> left: <span class="hljs-number">16</span>,<br> ),<br> child: <span class="hljs-type">Text</span>(<br> '副标题',<br> style: <span class="hljs-type">TextStyle</span>(<br> fontSize: <span class="hljs-number">13</span>,<br> ),<br> ),<br> ),<br> ),<br> flex: <span class="hljs-number">2</span>,<br> ),<br> ],<br> ),<br> ),<br> );<br> }<br> },<br> separatorBuilder: (context, index) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Divider</span>(<br> color: <span class="hljs-type">Colors</span>.grey,<br> height: <span class="hljs-number">0.5</span>,<br> );<br> },<br> itemCount: (_dataList.length),<br> ),<br> ),<br> );<br> }<br>}<br><br></code></pre></td></tr></table></figure><h4 id="4、GridView"><a href="#4、GridView" class="headerlink" title="4、GridView"></a>4、GridView</h4><p>暂不学习</p><h4 id="5、CustomScrollView"><a href="#5、CustomScrollView" class="headerlink" title="5、CustomScrollView"></a>5、CustomScrollView</h4><p>假设有一个页面,顶部需要一个<code>GridView</code>,底部需要一个<code>ListView</code>,而要求整个页面的滑动效果是统一的,即它们看起来是一个整体。如果使用<code>GridView+ListView</code>来实现的话,就不能保证一致的滑动效果,因为它们的滚动效果是分离的,所以这时就需要一个“胶水”,把这些彼此独立的可滚动组件“粘”起来,而<code>CustomScrollView</code>的功能就相当于“胶水”</p><h4 id="6、滚动监听及控制"><a href="#6、滚动监听及控制" class="headerlink" title="6、滚动监听及控制"></a>6、滚动监听及控制</h4><p><span style="color: lightgray;"><em>未完待续</em></span></p>]]></content>
<categories>
<category>flutter</category>
</categories>
<tags>
<tag>flutter</tag>
<tag>学习日记</tag>
</tags>
</entry>
<entry>
<title>Flutter学习日记-log3</title>
<link href="/2020/03/06/Flutter%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log3/"/>
<url>/2020/03/06/Flutter%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log3/</url>
<content type="html"><![CDATA[<blockquote><p><a href="https://flutterchina.club/get-started/install/"><em>Flutter中文网</em></a></p></blockquote><hr><h2 id="日志随笔"><a href="#日志随笔" class="headerlink" title="日志随笔"></a>日志随笔</h2><h3 id="一、复习"><a href="#一、复习" class="headerlink" title="一、复习"></a>一、复习</h3><ul><li>命名路由</li><li>路由传参</li></ul><h3 id="二、状态管理"><a href="#二、状态管理" class="headerlink" title="二、状态管理"></a>二、状态管理</h3><ul><li><code>Widget</code>管理自身状态</li><li>父<code>Widget</code>管理子<code>Widget</code>状态,在子<code>Widget</code>上包裹一层父<code>Widget</code>,子<code>Widget</code>把状态调整的方法对外提供成参数给父<code>Widget</code><ul><li><code>GestureDetector</code>手势,<code>onTap</code>等方法</li><li><code>Container</code>绘制矩形区域,<code>decoration</code>属性设置背景、边框等,<code>decoration</code>里面<code>color</code>字段和<code>Container</code>本身的<code>color</code>字段不能同时设置,会报错,使用<code>padding</code>调整位置,或者使用<code>Center</code>包裹居中</li></ul></li><li>混合管理状态</li><li>全局状态管理,例如国际化等操作,此处暂不学习</li></ul><figure class="highlight scala"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br></pre></td><td class="code"><pre><code class="hljs scala"><span class="hljs-keyword">import</span> <span class="hljs-symbol">'package</span>:flutter/material.dart';<br><br>void main() => runApp(<span class="hljs-type">MyApp</span>());<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">MaterialApp</span>(<br> title: '状态管理',<br> theme: <span class="hljs-type">ThemeData</span>(<br> primarySwatch: <span class="hljs-type">Colors</span>.blue,<br> ),<br> initialRoute: <span class="hljs-symbol">'HomePag</span>e',<br> routes: {<br> <span class="hljs-symbol">'HomePag</span>e': (context) => <span class="hljs-type">HomePage</span>(),<br> },<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HomePage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>('首页'),<br> ),<br> body: <span class="hljs-type">Center</span>(<br> child: <span class="hljs-type">Column</span>(<br> mainAxisAlignment: <span class="hljs-type">MainAxisAlignment</span>.start,<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">Text</span>(<br> '这是首页',<br> style: <span class="hljs-type">TextStyle</span>(<br> color: <span class="hljs-type">Colors</span>.blue,<br> fontSize: <span class="hljs-number">20</span>,<br> ),<br> ),<br> <span class="hljs-type">TapboxA</span>(),<br> <span class="hljs-type">ParentWidget</span>(),<br> <span class="hljs-type">ParentWidgetC</span>(),<br> ],<br> ),<br> ),<br> );<br> }<br>}<br><br><span class="hljs-comment">// TapboxA 管理自身状态.</span><br><br><span class="hljs-comment">//------------------------- TapboxA ----------------------------------</span><br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TapboxA</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> _TapboxAState createState() => _TapboxAState();<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_TapboxAState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<TapboxA></span> </span>{<br> bool _active = <span class="hljs-literal">false</span>;<br> void _handleTap() {<br> setState(() {<br> _active = !_active;<br> });<br> }<br><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">GestureDetector</span>(<br> child: <span class="hljs-type">Container</span>(<br> child: <span class="hljs-type">Center</span>(<br> child: <span class="hljs-type">Text</span>(<br> _active ? <span class="hljs-symbol">'0</span>0' : <span class="hljs-symbol">'9</span>9',<br> style: <span class="hljs-type">TextStyle</span>(<br> fontSize: <span class="hljs-number">100</span>,<br> color: <span class="hljs-type">Colors</span>.white,<br> backgroundColor: _active ? <span class="hljs-type">Colors</span>.red : <span class="hljs-type">Colors</span>.blue,<br> ),<br> ),<br> ),<br> width: <span class="hljs-number">200</span>,<br> height: <span class="hljs-number">200</span>,<br> padding: <span class="hljs-type">EdgeInsets</span>.only(left: <span class="hljs-number">20</span>),<br> decoration: <span class="hljs-type">BoxDecoration</span>(<br> color: <span class="hljs-type">Colors</span>.orange,<br> border: <span class="hljs-type">Border</span>(<br> top: <span class="hljs-type">BorderSide</span>(<br> color: <span class="hljs-type">Colors</span>.black,<br> width: <span class="hljs-number">10</span>,<br> style: <span class="hljs-type">BorderStyle</span>.solid,<br> )),<br> <span class="hljs-comment">// border: Border.all(</span><br> <span class="hljs-comment">// color: Colors.black,</span><br> <span class="hljs-comment">// width: 10,</span><br> <span class="hljs-comment">// style: BorderStyle.solid,</span><br> <span class="hljs-comment">// ),</span><br> ),<br> ),<br> onTap: _handleTap,<br> );<br> }<br>}<br><br><span class="hljs-comment">// ParentWidget 为 TapboxB 管理状态.</span><br><br><span class="hljs-comment">//------------------------ ParentWidget --------------------------------</span><br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ParentWidget</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> _ParentWidgetState createState() => _ParentWidgetState();<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_ParentWidgetState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<ParentWidget></span> </span>{<br> bool _active = <span class="hljs-literal">false</span>;<br><br> void _handleTapboxChanged(bool newValue) {<br> setState(() {<br> _active = newValue;<br> });<br> }<br><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-type">Container</span>(<br> child: <span class="hljs-keyword">new</span> <span class="hljs-type">TapboxB</span>(<br> active: _active,<br> onChanged: _handleTapboxChanged,<br> ),<br> );<br> }<br>}<br><br><span class="hljs-comment">//------------------------- TapboxB ----------------------------------</span><br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TapboxB</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-keyword">final</span> bool active;<br> <span class="hljs-keyword">final</span> <span class="hljs-type">ValueChanged</span><bool> onChanged;<br><br> <span class="hljs-type">TapboxB</span>({<br> <span class="hljs-type">Key</span> key, <br> <span class="hljs-keyword">this</span>.active: <span class="hljs-literal">false</span>, <br> <span class="hljs-meta">@required</span> <span class="hljs-keyword">this</span>.onChanged<br> }): <span class="hljs-keyword">super</span>(key: key);<br><br> void _handleTap() {<br> onChanged(!active);<br> }<br><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-type">GestureDetector</span>(<br> onTap: _handleTap,<br> child: <span class="hljs-keyword">new</span> <span class="hljs-type">Container</span>(<br> child: <span class="hljs-keyword">new</span> <span class="hljs-type">Center</span>(<br> child: <span class="hljs-keyword">new</span> <span class="hljs-type">Text</span>(<br> active ? <span class="hljs-symbol">'Activ</span>e' : <span class="hljs-symbol">'Inactiv</span>e',<br> style: <span class="hljs-keyword">new</span> <span class="hljs-type">TextStyle</span>(fontSize: <span class="hljs-number">32.0</span>, color: <span class="hljs-type">Colors</span>.white),<br> ),<br> ),<br> width: <span class="hljs-number">200.0</span>,<br> height: <span class="hljs-number">200.0</span>,<br> decoration: <span class="hljs-keyword">new</span> <span class="hljs-type">BoxDecoration</span>(<br> color: active ? <span class="hljs-type">Colors</span>.lightGreen[<span class="hljs-number">700</span>] : <span class="hljs-type">Colors</span>.grey[<span class="hljs-number">600</span>],<br> ),<br> ),<br> );<br> }<br>}<br><br><span class="hljs-comment">//---------------------------- ParentWidget ----------------------------</span><br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ParentWidgetC</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> _ParentWidgetCState createState() => <span class="hljs-keyword">new</span> _ParentWidgetCState();<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_ParentWidgetCState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<ParentWidgetC></span> </span>{<br> bool _active = <span class="hljs-literal">false</span>;<br><br> void _handleTapboxChanged(bool newValue) {<br> setState(() {<br> _active = newValue;<br> });<br> }<br><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-type">Container</span>(<br> child: <span class="hljs-keyword">new</span> <span class="hljs-type">TapboxC</span>(<br> active: _active,<br> onChanged: _handleTapboxChanged,<br> ),<br> );<br> }<br>}<br><br><span class="hljs-comment">//----------------------------- TapboxC ------------------------------</span><br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TapboxC</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> <span class="hljs-type">TapboxC</span>({<span class="hljs-type">Key</span> key, <span class="hljs-keyword">this</span>.active: <span class="hljs-literal">false</span>, <span class="hljs-meta">@required</span> <span class="hljs-keyword">this</span>.onChanged})<br> : <span class="hljs-keyword">super</span>(key: key);<br><br> <span class="hljs-keyword">final</span> bool active;<br> <span class="hljs-keyword">final</span> <span class="hljs-type">ValueChanged</span><bool> onChanged;<br><br> <span class="hljs-meta">@override</span><br> _TapboxCState createState() => <span class="hljs-keyword">new</span> _TapboxCState();<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_TapboxCState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<TapboxC></span> </span>{<br> bool _highlight = <span class="hljs-literal">false</span>;<br><br> void _handleTapDown(<span class="hljs-type">TapDownDetails</span> details) {<br> setState(() {<br> _highlight = <span class="hljs-literal">true</span>;<br> });<br> }<br><br> void _handleTapUp(<span class="hljs-type">TapUpDetails</span> details) {<br> setState(() {<br> _highlight = <span class="hljs-literal">false</span>;<br> });<br> }<br><br> void _handleTapCancel() {<br> setState(() {<br> _highlight = <span class="hljs-literal">false</span>;<br> });<br> }<br><br> void _handleTap() {<br> widget.onChanged(!widget.active);<br> }<br><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-comment">// 在按下时添加绿色边框,当抬起时,取消高亮 </span><br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-type">GestureDetector</span>(<br> onTapDown: _handleTapDown, <span class="hljs-comment">// 处理按下事件</span><br> onTapUp: _handleTapUp, <span class="hljs-comment">// 处理抬起事件</span><br> onTap: _handleTap,<br> onTapCancel: _handleTapCancel,<br> child: <span class="hljs-keyword">new</span> <span class="hljs-type">Container</span>(<br> child: <span class="hljs-keyword">new</span> <span class="hljs-type">Center</span>(<br> child: <span class="hljs-keyword">new</span> <span class="hljs-type">Text</span>(widget.active ? <span class="hljs-symbol">'Activ</span>e' : <span class="hljs-symbol">'Inactiv</span>e',<br> style: <span class="hljs-keyword">new</span> <span class="hljs-type">TextStyle</span>(fontSize: <span class="hljs-number">32.0</span>, color: <span class="hljs-type">Colors</span>.white)),<br> ),<br> width: <span class="hljs-number">200.0</span>,<br> height: <span class="hljs-number">200.0</span>,<br> decoration: <span class="hljs-keyword">new</span> <span class="hljs-type">BoxDecoration</span>(<br> color: widget.active ? <span class="hljs-type">Colors</span>.lightGreen[<span class="hljs-number">700</span>] : <span class="hljs-type">Colors</span>.grey[<span class="hljs-number">600</span>],<br> border: _highlight<br> ? <span class="hljs-keyword">new</span> <span class="hljs-type">Border</span>.all(<br> color: <span class="hljs-type">Colors</span>.teal[<span class="hljs-number">700</span>],<br> width: <span class="hljs-number">10.0</span>,<br> )<br> : <span class="hljs-literal">null</span>,<br> ),<br> ),<br> );<br> }<br>}<br><br></code></pre></td></tr></table></figure><h3 id="三、组件和组件样式"><a href="#三、组件和组件样式" class="headerlink" title="三、组件和组件样式"></a>三、组件和组件样式</h3><h4 id="1、文本"><a href="#1、文本" class="headerlink" title="1、文本"></a>1、文本</h4><ul><li>基础样式:<code>textAlign</code>、<code>maxLines</code>、<code>overflow</code>、<code>textScaleFactor</code>等</li><li>高级一点的直接定制<code>TextStyle</code>属性</li><li><code>TextSpan</code>实现富文本样式</li><li><code>DefaultTextStyle</code>样式继承</li><li>字体:使用<a href="https://fonts.google.com/"><code>Google Fonts</code></a>中的字体,首先在<code>pubspec.yaml</code>中声明,然后通过<code>TextStyle</code>属性使用</li></ul><h4 id="2、按钮"><a href="#2、按钮" class="headerlink" title="2、按钮"></a>2、按钮</h4><blockquote><p>此处学习基于<code>Android</code>端的<code>Material</code>组件,所有<code>Material</code> 库中的按钮都是直接或间接的<code>RawMaterialButton</code>组件的包装定制,都有如下相同点:</p><ol><li>按下时都会有“水波动画”(又称“涟漪动画”,就是点击时按钮上会出现水波荡漾的动画)</li><li>有一个<code>onPressed</code>属性来设置点击回调,当按钮按下时会执行该回调,如果不提供该回调则按钮会处于禁用状态,禁用状态不响应用户点击</li></ol></blockquote><ul><li><code>RaisedButton</code>漂浮按钮,文字+图标</li><li><code>FlatButton</code>扁平按钮,文字+图标<ul><li><code>highlightColor</code>和<code>splashColor</code>冲突,前者设置后,后者的效果就没了,暂不研究</li><li><code>shape</code>属性是<code>ShapeBorder</code>类的,但<code>ShapeBorder</code>不直接使用,应该使用该类的子类,子类提供了具体的样式效果<figure class="highlight kotlin"><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><code class="hljs kotlin"><span class="hljs-keyword">const</span> FlatButton({<br> ... <br> <span class="hljs-meta">@required</span> <span class="hljs-keyword">this</span>.onPressed, <span class="hljs-comment">//按钮点击回调</span><br> <span class="hljs-keyword">this</span>.textColor, <span class="hljs-comment">//按钮文字颜色</span><br> <span class="hljs-keyword">this</span>.disabledTextColor, <span class="hljs-comment">//按钮禁用时的文字颜色</span><br> <span class="hljs-keyword">this</span>.color, <span class="hljs-comment">//按钮背景颜色</span><br> <span class="hljs-keyword">this</span>.disabledColor,<span class="hljs-comment">//按钮禁用时的背景颜色</span><br> <span class="hljs-keyword">this</span>.highlightColor, <span class="hljs-comment">//按钮按下时的背景颜色</span><br> <span class="hljs-keyword">this</span>.splashColor, <span class="hljs-comment">//点击时,水波动画中水波的颜色</span><br> <span class="hljs-keyword">this</span>.colorBrightness,<span class="hljs-comment">//按钮主题,默认是浅色主题 </span><br> <span class="hljs-keyword">this</span>.padding, <span class="hljs-comment">//按钮的填充</span><br> <span class="hljs-keyword">this</span>.shape, <span class="hljs-comment">//外形</span><br> <span class="hljs-meta">@required</span> <span class="hljs-keyword">this</span>.child, <span class="hljs-comment">//按钮的内容</span><br>})<br></code></pre></td></tr></table></figure></li></ul></li><li><code>OutlineButton</code>边框按钮,文字+图标</li><li><code>IconButton</code>图标按钮,没有文字</li></ul><figure class="highlight scala"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br></pre></td><td class="code"><pre><code class="hljs scala"><span class="hljs-keyword">import</span> <span class="hljs-symbol">'package</span>:flutter/material.dart';<br><br>void main() => runApp(<span class="hljs-type">MyApp</span>());<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-comment">// This widget is the root of your application.</span><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">MaterialApp</span>(<br> title: '控件样式',<br> theme: <span class="hljs-type">ThemeData</span>(<br> primarySwatch: <span class="hljs-type">Colors</span>.blue,<br> ),<br> initialRoute: <span class="hljs-symbol">'HomePag</span>e',<br> routes: {<br> <span class="hljs-symbol">'HomePag</span>e': (context) => <span class="hljs-type">HomePage</span>(),<br> },<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HomePage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> void _onPressed() {}<br><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-type">String</span> icons = <span class="hljs-string">""</span>;<br> <span class="hljs-comment">// accessible: &#xE914; or 0xE914 or E914</span><br> icons += <span class="hljs-string">"\uE914"</span>;<br> <span class="hljs-comment">// error: &#xE000; or 0xE000 or E000</span><br> icons += <span class="hljs-string">" \uE000"</span>;<br> <span class="hljs-comment">// fingerprint: &#xE90D; or 0xE90D or E90D</span><br> icons += <span class="hljs-string">" \uE90D"</span>;<br><br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>('首页'),<br> ),<br> body: <span class="hljs-type">Column</span>(<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">Container</span>(<br> child: <span class="hljs-type">Row</span>(<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">RaisedButton</span>(<br> child: <span class="hljs-type">Text</span>(<span class="hljs-string">"RaisedButton"</span>),<br> onPressed: () {},<br> ),<br> <span class="hljs-type">FlatButton</span>(<br> child: <span class="hljs-type">Text</span>(<span class="hljs-string">"FlatButton"</span>),<br> onPressed: () {},<br> ),<br> <span class="hljs-type">OutlineButton</span>(<br> child: <span class="hljs-type">Text</span>(<span class="hljs-string">"normal"</span>),<br> onPressed: () {},<br> ),<br> <span class="hljs-type">IconButton</span>(<br> icon: <span class="hljs-type">Icon</span>(<span class="hljs-type">Icons</span>.thumb_up),<br> onPressed: () {},<br> ),<br> ],<br> ),<br> ),<br> <span class="hljs-type">Container</span>(<br> child: <span class="hljs-type">Row</span>(<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">RaisedButton</span>.icon(<br> icon: <span class="hljs-type">Icon</span>(<span class="hljs-type">Icons</span>.send),<br> label: <span class="hljs-type">Text</span>(<span class="hljs-string">"发送"</span>),<br> onPressed: _onPressed,<br> ),<br> <span class="hljs-type">FlatButton</span>.icon(<br> icon: <span class="hljs-type">Icon</span>(<span class="hljs-type">Icons</span>.info),<br> label: <span class="hljs-type">Text</span>(<span class="hljs-string">"详情"</span>),<br> onPressed: _onPressed,<br> ),<br> <span class="hljs-type">OutlineButton</span>.icon(<br> icon: <span class="hljs-type">Icon</span>(<span class="hljs-type">Icons</span>.add),<br> label: <span class="hljs-type">Text</span>(<span class="hljs-string">"添加"</span>),<br> onPressed: _onPressed,<br> ),<br> ],<br> ),<br> ),<br> <span class="hljs-type">Container</span>(<br> child: <span class="hljs-type">Row</span>(<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">FlatButton</span>(<br> onPressed: _onPressed,<br> child: <span class="hljs-type">Text</span>(<span class="hljs-string">"提交"</span>),<br> color: <span class="hljs-type">Colors</span>.blue,<br> textColor: <span class="hljs-type">Colors</span>.white,<br> <span class="hljs-comment">// highlightColor: Colors.blue[700],</span><br> <span class="hljs-comment">// splashColor: Colors.grey,</span><br> shape: <span class="hljs-type">RoundedRectangleBorder</span>(<br> borderRadius: <span class="hljs-type">BorderRadius</span>.circular(<span class="hljs-number">20.0</span>),<br> ),<br> ),<br> <span class="hljs-type">RaisedButton</span>(<br> onPressed: _onPressed,<br> child: <span class="hljs-type">Text</span>(<span class="hljs-string">"提交"</span>),<br> color: <span class="hljs-type">Colors</span>.blue,<br> textColor: <span class="hljs-type">Colors</span>.white,<br> <span class="hljs-comment">// highlightColor: Colors.blue[700],</span><br> <span class="hljs-comment">// splashColor: Colors.grey,</span><br> shape: <span class="hljs-type">RoundedRectangleBorder</span>(<br> borderRadius: <span class="hljs-type">BorderRadius</span>.circular(<span class="hljs-number">20.0</span>),<br> ),<br> ),<br> ],<br> ),<br> ),<br> ],<br> ),<br> );<br> }<br>}<br><br></code></pre></td></tr></table></figure><h4 id="3、图片和图标"><a href="#3、图片和图标" class="headerlink" title="3、图片和图标"></a>3、图片和图标</h4><h5 id="1-图片"><a href="#1-图片" class="headerlink" title="1. 图片"></a>1. 图片</h5><ul><li><code>ImageProvider</code>是一个抽象类,从不同的数据源获取图片使用不同的方法,从<code>Asset</code>中加载图片使用<code>AssetImage</code>,从网络加载图片使用<code>NetworkImage</code></li><li><code>fit</code>属性<ul><li><code>fill</code>:会拉伸填充满显示空间,图片本身长宽比会发生变化,图片会变形。</li><li><code>cover</code>:会按图片的长宽比放大后居中填满显示空间,图片不会变形,超出显示空间部分会被剪裁。</li><li><code>contain</code>:这是图片的默认适应规则,图片会在保证图片本身长宽比不变的情况下缩放以适应当前显示空间,图片不会变形。</li><li><code>fitWidth</code>:图片的宽度会缩放到显示空间的宽度,高度会按比例缩放,然后居中显示,图片不会变形,超出显示空间部分会被剪裁。</li><li><code>fitHeight</code>:图片的高度会缩放到显示空间的高度,宽度会按比例缩放,然后居中显示,图片不会变形,超出显示空间部分会被剪裁。</li><li><code>none</code>:图片没有适应策略,会在显示空间内显示图片,如果图片比显示空间大,则显示空间只会显示图片中间部分。</li></ul></li></ul><p><img src="image_1.png" alt="image_1"></p><ul><li><code>Flutter</code>框架对加载过的图片是有缓存的(内存),默认最大缓存数量是<code>1000</code>,最大缓存空间为<code>100M</code>,此处暂不学习</li></ul><h5 id="2-图标"><a href="#2-图标" class="headerlink" title="2. 图标"></a>2. 图标</h5><p><code>Flutter</code>默认包含了一套<code>Material Design</code>的字体图标<code>iconfont</code>,<code>pubspec.yaml</code>文件中配置默认打开,官网地址:<a href="https://material.io/tools/icons/"><code>https://material.io/tools/icons/</code></a></p><h4 id="4、单选和复选框"><a href="#4、单选和复选框" class="headerlink" title="4、单选和复选框"></a>4、单选和复选框</h4><ul><li><code>Switch</code></li><li><code>Checkbox</code></li></ul><h4 id="5、输入框"><a href="#5、输入框" class="headerlink" title="5、输入框"></a>5、输入框</h4><ul><li><code>onChange</code>方法通知输入框文本发生变化</li><li>创建<code>TextEditingController</code>控制器,绑定输入框<ul><li>设置占位文本,比输入框本身的属性优先级高</li><li>获取绑定的输入框内的文本</li><li>创建<code>FocusNode</code>,绑定输入框,来控制键盘焦点</li></ul></li></ul><h4 id="6、Form表单"><a href="#6、Form表单" class="headerlink" title="6、Form表单"></a>6、<code>Form</code>表单</h4><p><code>Form</code>表单是基于输入框封装的一个功能更完善的控件,需要对应<code>TextFormField</code>的使用,可以实现<code>validate</code>方法对所有输入框条件的一键验证</p><figure class="highlight scala"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br></pre></td><td class="code"><pre><code class="hljs scala"><span class="hljs-keyword">import</span> <span class="hljs-symbol">'package</span>:flutter/material.dart';<br><br>void main() => runApp(<span class="hljs-type">MyApp</span>());<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-comment">// This widget is the root of your application.</span><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">MaterialApp</span>(<br> title: '表单',<br> theme: <span class="hljs-type">ThemeData</span>(<br> primarySwatch: <span class="hljs-type">Colors</span>.blue,<br> ),<br> home: <span class="hljs-type">FormTestRoute</span>(),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FormTestRoute</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> _FormTestRouteState createState() => <span class="hljs-keyword">new</span> _FormTestRouteState();<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_FormTestRouteState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<FormTestRoute></span> </span>{<br> <span class="hljs-type">TextEditingController</span> _unameController = <span class="hljs-keyword">new</span> <span class="hljs-type">TextEditingController</span>();<br> <span class="hljs-type">TextEditingController</span> _pwdController = <span class="hljs-keyword">new</span> <span class="hljs-type">TextEditingController</span>();<br> <span class="hljs-type">GlobalKey</span> _formKey = <span class="hljs-keyword">new</span> <span class="hljs-type">GlobalKey</span><<span class="hljs-type">FormState</span>>();<br><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(<span class="hljs-string">"Form Test"</span>),<br> ),<br> body: <span class="hljs-type">Padding</span>(<br> padding: const <span class="hljs-type">EdgeInsets</span>.symmetric(vertical: <span class="hljs-number">16.0</span>, horizontal: <span class="hljs-number">24.0</span>),<br> child: <span class="hljs-type">Form</span>(<br> key: _formKey, <span class="hljs-comment">//设置globalKey,用于后面获取FormState</span><br> autovalidate: <span class="hljs-literal">true</span>, <span class="hljs-comment">//开启自动校验</span><br> child: <span class="hljs-type">Column</span>(<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">TextFormField</span>(<br> autofocus: <span class="hljs-literal">true</span>,<br> controller: _unameController,<br> decoration: <span class="hljs-type">InputDecoration</span>(<br> labelText: <span class="hljs-string">"用户名"</span>,<br> hintText: <span class="hljs-string">"用户名或邮箱"</span>,<br> icon: <span class="hljs-type">Icon</span>(<span class="hljs-type">Icons</span>.person)),<br> <span class="hljs-comment">// 校验用户名</span><br> validator: (v) {<br> <span class="hljs-keyword">return</span> v.trim().length > <span class="hljs-number">0</span> ? <span class="hljs-literal">null</span> : <span class="hljs-string">"用户名不能为空"</span>;<br> }),<br> <span class="hljs-type">TextFormField</span>(<br> controller: _pwdController,<br> decoration: <span class="hljs-type">InputDecoration</span>(<br> labelText: <span class="hljs-string">"密码"</span>,<br> hintText: <span class="hljs-string">"您的登录密码"</span>,<br> icon: <span class="hljs-type">Icon</span>(<span class="hljs-type">Icons</span>.lock)),<br> obscureText: <span class="hljs-literal">true</span>,<br> <span class="hljs-comment">//校验密码</span><br> validator: (v) {<br> <span class="hljs-keyword">return</span> v.trim().length > <span class="hljs-number">5</span> ? <span class="hljs-literal">null</span> : <span class="hljs-string">"密码不能少于6位"</span>;<br> }),<br> <span class="hljs-comment">// 登录按钮</span><br> <span class="hljs-type">Padding</span>(<br> padding: const <span class="hljs-type">EdgeInsets</span>.only(top: <span class="hljs-number">28.0</span>),<br> child: <span class="hljs-type">Row</span>(<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">Expanded</span>(<br> child: <span class="hljs-type">RaisedButton</span>(<br> padding: <span class="hljs-type">EdgeInsets</span>.all(<span class="hljs-number">15.0</span>),<br> child: <span class="hljs-type">Text</span>(<span class="hljs-string">"登录"</span>),<br> color: <span class="hljs-type">Theme</span>.of(context).primaryColor,<br> textColor: <span class="hljs-type">Colors</span>.white,<br> onPressed: () {<br> <span class="hljs-comment">//在这里不能通过此方式获取FormState,context不对</span><br> <span class="hljs-comment">//print(Form.of(context));</span><br><br> <span class="hljs-comment">// 通过_formKey.currentState 获取FormState后,</span><br> <span class="hljs-comment">// 调用validate()方法校验用户名密码是否合法,校验</span><br> <span class="hljs-comment">// 通过后再提交数据。</span><br> <span class="hljs-keyword">if</span> ((_formKey.currentState as <span class="hljs-type">FormState</span>).validate()) {<br> <span class="hljs-comment">//验证通过提交数据</span><br> debugPrint('通过');<br> }<br> },<br> ),<br> ),<br> ],<br> ),<br> )<br> ],<br> ),<br> ),<br> ),<br> );<br> }<br>}<br><br></code></pre></td></tr></table></figure><h4 id="7、进度条指示器"><a href="#7、进度条指示器" class="headerlink" title="7、进度条指示器"></a>7、进度条指示器</h4><figure class="highlight scala"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br></pre></td><td class="code"><pre><code class="hljs scala"><span class="hljs-keyword">import</span> <span class="hljs-symbol">'package</span>:flutter/material.dart';<br><br>void main() => runApp(<span class="hljs-type">MyApp</span>());<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">MaterialApp</span>(<br> title: '进度条控件',<br> theme: <span class="hljs-type">ThemeData</span>(<br> primarySwatch: <span class="hljs-type">Colors</span>.blue,<br> ),<br> home: <span class="hljs-type">MyHomePage</span>(),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyHomePage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> _MyHomePageState createState() => _MyHomePageState();<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_MyHomePageState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<MyHomePage></span></span><br><span class="hljs-class"> <span class="hljs-keyword">with</span> <span class="hljs-title">SingleTickerProviderStateMixin</span> </span>{<br> <span class="hljs-type">AnimationController</span> _animationController;<br><br> <span class="hljs-meta">@override</span><br> void initState() {<br> <span class="hljs-comment">//动画执行时间3秒</span><br> _animationController =<br> <span class="hljs-keyword">new</span> <span class="hljs-type">AnimationController</span>(vsync: <span class="hljs-keyword">this</span>, duration: <span class="hljs-type">Duration</span>(seconds: <span class="hljs-number">3</span>));<br> _animationController.forward();<br> _animationController.addListener(() => setState(() => {}));<br> <span class="hljs-keyword">super</span>.initState();<br> }<br><br> <span class="hljs-meta">@override</span><br> void dispose() {<br> _animationController.dispose();<br> <span class="hljs-keyword">super</span>.dispose();<br> }<br><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>('主页'),<br> ),<br> body: <span class="hljs-type">Column</span>(<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">LinearProgressIndicator</span>(<br> backgroundColor: <span class="hljs-type">Colors</span>.grey[<span class="hljs-number">200</span>],<br> valueColor: <span class="hljs-type">AlwaysStoppedAnimation</span>(<span class="hljs-type">Colors</span>.blue),<br> ),<br> <span class="hljs-comment">//进度条显示50%</span><br> <span class="hljs-type">LinearProgressIndicator</span>(<br> backgroundColor: <span class="hljs-type">Colors</span>.grey[<span class="hljs-number">200</span>],<br> valueColor: <span class="hljs-type">AlwaysStoppedAnimation</span>(<span class="hljs-type">Colors</span>.blue),<br> value: <span class="hljs-number">.5</span>,<br> ),<br> <span class="hljs-comment">// 模糊进度条(会执行一个旋转动画)</span><br> <span class="hljs-type">CircularProgressIndicator</span>(<br> backgroundColor: <span class="hljs-type">Colors</span>.grey[<span class="hljs-number">200</span>],<br> valueColor: <span class="hljs-type">AlwaysStoppedAnimation</span>(<span class="hljs-type">Colors</span>.blue),<br> ),<br> <span class="hljs-comment">//进度条显示50%,会显示一个半圆</span><br> <span class="hljs-type">CircularProgressIndicator</span>(<br> backgroundColor: <span class="hljs-type">Colors</span>.grey[<span class="hljs-number">200</span>],<br> valueColor: <span class="hljs-type">AlwaysStoppedAnimation</span>(<span class="hljs-type">Colors</span>.blue),<br> value: <span class="hljs-number">.5</span>,<br> ),<br> <span class="hljs-comment">// 线性进度条高度指定为3</span><br> <span class="hljs-type">SizedBox</span>(<br> height: <span class="hljs-number">3</span>,<br> child: <span class="hljs-type">LinearProgressIndicator</span>(<br> backgroundColor: <span class="hljs-type">Colors</span>.grey[<span class="hljs-number">200</span>],<br> valueColor: <span class="hljs-type">AlwaysStoppedAnimation</span>(<span class="hljs-type">Colors</span>.blue),<br> value: <span class="hljs-number">.5</span>,<br> ),<br> ),<br> <span class="hljs-comment">// 圆形进度条直径指定为100</span><br> <span class="hljs-type">SizedBox</span>(<br> height: <span class="hljs-number">100</span>,<br> width: <span class="hljs-number">100</span>,<br> child: <span class="hljs-type">CircularProgressIndicator</span>(<br> backgroundColor: <span class="hljs-type">Colors</span>.grey[<span class="hljs-number">200</span>],<br> valueColor: <span class="hljs-type">AlwaysStoppedAnimation</span>(<span class="hljs-type">Colors</span>.blue),<br> value: <span class="hljs-number">.7</span>,<br> ),<br> ),<br> <span class="hljs-comment">// 宽高不等</span><br> <span class="hljs-type">SizedBox</span>(<br> height: <span class="hljs-number">100</span>,<br> width: <span class="hljs-number">130</span>,<br> child: <span class="hljs-type">CircularProgressIndicator</span>(<br> backgroundColor: <span class="hljs-type">Colors</span>.grey[<span class="hljs-number">200</span>],<br> valueColor: <span class="hljs-type">AlwaysStoppedAnimation</span>(<span class="hljs-type">Colors</span>.blue),<br> value: <span class="hljs-number">.7</span>,<br> ),<br> ),<br> <span class="hljs-type">LinearProgressIndicator</span>(<br> backgroundColor: <span class="hljs-type">Colors</span>.grey[<span class="hljs-number">200</span>],<br> valueColor: <span class="hljs-type">ColorTween</span>(begin: <span class="hljs-type">Colors</span>.grey, end: <span class="hljs-type">Colors</span>.blue)<br> .animate(_animationController), <span class="hljs-comment">// 从灰色变成蓝色</span><br> value: _animationController.value,<br> ),<br> ],<br> ),<br> );<br> }<br>}<br><br></code></pre></td></tr></table></figure><h3 id="四、布局"><a href="#四、布局" class="headerlink" title="四、布局"></a>四、布局</h3><h4 id="1、线性布局(Row和Column)"><a href="#1、线性布局(Row和Column)" class="headerlink" title="1、线性布局(Row和Column)"></a>1、线性布局(<code>Row</code>和<code>Column</code>)</h4><ul><li><code>Row</code>和<code>Column</code>会在主轴方向占用尽可能大的空间,而纵轴的长度则取决于他们最大子元素的长度</li><li>如果<code>Row</code>里面嵌套<code>Row</code>,或者<code>Column</code>里面再嵌套<code>Column</code>,那么只有最外面的<code>Row</code>或<code>Column</code>会占用尽可能大的空间,里面<code>Row</code>或<code>Column</code>所占用的空间为实际大小</li></ul><h4 id="2、弹性布局(Flex)"><a href="#2、弹性布局(Flex)" class="headerlink" title="2、弹性布局(Flex)"></a>2、弹性布局(<code>Flex</code>)</h4><ul><li><code>Row</code>和<code>Column</code>都继承自<code>Flex</code></li><li><code>Expanded</code>可以按比例“扩伸”<code>Row</code>、<code>Column</code>和<code>Flex</code>子组件所占用的空间</li><li><code>Spacer</code>的功能是占用指定比例的空间</li></ul><h4 id="3、流式布局(Wrap和Flow)"><a href="#3、流式布局(Wrap和Flow)" class="headerlink" title="3、流式布局(Wrap和Flow)"></a>3、流式布局(<code>Wrap</code>和<code>Flow</code>)</h4><ul><li>超出屏幕显示范围会自动折行的布局称为流式布局</li><li>一般很少会使用<code>Flow</code></li></ul><h4 id="4、层叠布局(Stack和Positioned)"><a href="#4、层叠布局(Stack和Positioned)" class="headerlink" title="4、层叠布局(Stack和Positioned)"></a>4、层叠布局(<code>Stack</code>和<code>Positioned</code>)</h4><ul><li><code>Stack</code>允许子组件堆叠</li><li><code>Positioned</code>用于根据<code>Stack</code>的四个角来确定子组件的位置</li><li><code>Stack</code>和<code>Positioned</code>最好一起搭配使用</li></ul><h4 id="5、对齐与相对定位(Align)"><a href="#5、对齐与相对定位(Align)" class="headerlink" title="5、对齐与相对定位(Align)"></a>5、对齐与相对定位(<code>Align</code>)</h4><h5 id="1-Alignment"><a href="#1-Alignment" class="headerlink" title="1. Alignment"></a>1. <code>Alignment</code></h5><ul><li><code>Alignment</code>会以矩形的中心点作为坐标原点,即<code>Alignment(0.0, 0.0)</code>,<code>x</code>、<code>y</code>的值从<code>-1</code>到<code>1</code>分别代表矩形左边到右边的距离和顶部到底边的距离</li><li>计算公式:<code>(Alignment.x*childWidth/2+childWidth/2, Alignment.y*childHeight/2+childHeight/2)</code></li></ul><h5 id="2-FractionalOffset"><a href="#2-FractionalOffset" class="headerlink" title="2. FractionalOffset"></a>2. <code>FractionalOffset</code></h5><ul><li><code>FractionalOffset</code>继承自<code>Alignment</code>,它和<code>Alignment</code>唯一的区别就是坐标原点不同,<code>FractionalOffset</code>的坐标原点为矩形的左侧顶点</li><li>计算公式:<code>实际偏移 = (FractionalOffse.x * childWidth, FractionalOffse.y * childHeight)</code></li></ul><h5 id="3-Align和Stack对比"><a href="#3-Align和Stack对比" class="headerlink" title="3. Align和Stack对比"></a>3. <code>Align</code>和<code>Stack</code>对比</h5><ul><li>定位参考系统不同</li><li><code>Stack</code>可以有多个子元素,并且子元素可以堆叠,而<code>Align</code>只能有一个子元素,不存在堆叠</li><li><code>Center</code>继承自<code>Align</code>,可以认为<code>Center</code>组件其实是对齐方式确定<code>(Alignment.center)</code>了的<code>Align</code></li></ul><p><span style="color: lightgray;"><em>未完待续</em></span></p>]]></content>
<categories>
<category>flutter</category>
</categories>
<tags>
<tag>flutter</tag>
<tag>学习日记</tag>
</tags>
</entry>
<entry>
<title>Flutter学习日记-log2</title>
<link href="/2020/03/05/Flutter%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log2/"/>
<url>/2020/03/05/Flutter%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log2/</url>
<content type="html"><![CDATA[<blockquote><p><a href="https://flutterchina.club/get-started/install/"><em>Flutter中文网</em></a></p></blockquote><hr><h2 id="日志随笔"><a href="#日志随笔" class="headerlink" title="日志随笔"></a>日志随笔</h2><h3 id="一、复习第一天内容"><a href="#一、复习第一天内容" class="headerlink" title="一、复习第一天内容"></a>一、复习第一天内容</h3><ul><li><code>StatefulWidget</code>修改<code>State</code>状态,需要刷新<code>build</code>方法,所以需要单独创建<code>State</code>,并且把<code>build</code>方法写在<code>State</code>中</li><li><code>async</code>和<code>await</code>必须成对使用,否则<code>VS Code</code>会提示<code>fix</code></li></ul><h3 id="二、命名路由"><a href="#二、命名路由" class="headerlink" title="二、命名路由"></a>二、命名路由</h3><ul><li><code>MaterialApp</code>类存在属性<code>routes</code>,代表路由表,值是键值对<code>Map</code>形式</li><li><code>initialRoute</code>字段定义初始页面别名,在路由表<code>routes</code>中配置相应的初始页面别名,即可以正常进入初始页面</li><li><code>Navigator.pushNamed</code>方法可以直接使用路由别名进行跳转</li></ul><figure class="highlight typescript"><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><code class="hljs typescript"><span class="hljs-meta">@override</span><br>Wid<span class="hljs-keyword">get</span> <span class="hljs-title">build</span>(<span class="hljs-params">BuildContext context</span>) {<br> <span class="hljs-keyword">return</span> MaterialApp(<br> routes: {<br> <span class="hljs-string">"pageName"</span>: <span class="hljs-function">(<span class="hljs-params">context</span>) =></span> PageRoute()<br> }<br> );<br>}<br></code></pre></td></tr></table></figure><h3 id="三、路由传参的拓展"><a href="#三、路由传参的拓展" class="headerlink" title="三、路由传参的拓展"></a>三、路由传参的拓展</h3><h4 id="1、接受参数的两种方式和分别对应的发送参数方法"><a href="#1、接受参数的两种方式和分别对应的发送参数方法" class="headerlink" title="1、接受参数的两种方式和分别对应的发送参数方法"></a>1、接受参数的两种方式和分别对应的发送参数方法</h4><h5 id="1-接受方法在build方法外部,使用指定的语法直接接收"><a href="#1-接受方法在build方法外部,使用指定的语法直接接收" class="headerlink" title="1. 接受方法在build方法外部,使用指定的语法直接接收"></a>1. 接受方法在<code>build</code>方法外部,使用指定的语法直接接收</h5><ul><li>接收参数的方法</li></ul><figure class="highlight processing"><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><code class="hljs processing">ParamsRoute({<br> Key <span class="hljs-built_in">key</span>, <br> @required <span class="hljs-keyword">this</span>.params<br>}) : <span class="hljs-keyword">super</span>(<span class="hljs-built_in">key</span>: <span class="hljs-built_in">key</span>);<br><span class="hljs-keyword">final</span> params;<br></code></pre></td></tr></table></figure><ul><li>发送参数的方法</li></ul><figure class="highlight reasonml"><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><code class="hljs reasonml"><span class="hljs-comment">// 第一种方式</span><br>onPressed: <span class="hljs-literal">()</span> async {<br> var backparams = await <span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">Navigator</span>.</span></span>push(context, <span class="hljs-constructor">MaterialPageRoute(<span class="hljs-params">builder</span>: (<span class="hljs-params">newpage</span>)</span> {<br> return <span class="hljs-constructor">ParamsRoute(<span class="hljs-params">params</span>: <span class="hljs-string">""</span>)</span>;<br> }));<br> print(backparams);<br>}<br></code></pre></td></tr></table></figure><figure class="highlight typescript"><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></pre></td><td class="code"><pre><code class="hljs typescript"><span class="hljs-comment">// 第二种路由方式</span><br><span class="hljs-meta">@override</span><br>Wid<span class="hljs-keyword">get</span> <span class="hljs-title">build</span>(<span class="hljs-params">BuildContext context</span>) {<br> <span class="hljs-keyword">return</span> MaterialApp(<br> <span class="hljs-comment">// 先注册路由表</span><br> routes: {<br> <span class="hljs-string">"ParamsRoute"</span>: (context) {<br> <span class="hljs-keyword">return</span> ParamsRoute(params: ModalRoute.of(context).settings.arguments);<br> }<br> }<br> );<br>}<br><br><span class="hljs-comment">// 传参调用方法</span><br>onPressed: () <span class="hljs-keyword">async</span> {<br> <span class="hljs-keyword">var</span> backparams = <span class="hljs-keyword">await</span> Navigator.of(context).pushNamed(<span class="hljs-string">"ParamsRoute"</span>, <span class="hljs-attr">arguments</span>: <span class="hljs-string">""</span>);<br> print(backparams);<br>}<br></code></pre></td></tr></table></figure><ol start="2"><li>通过<code>build</code>方法中的<code>context</code>参数,使用<code>ModalRoute.of</code>的方法读取其中的参数值</li></ol><ul><li>接收参数的方法</li></ul><figure class="highlight javascript"><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><code class="hljs javascript">Wid<span class="hljs-keyword">get</span> <span class="hljs-title">build</span>(<span class="hljs-params">BuildContext context</span>) {<br> <span class="hljs-keyword">var</span> params = ModalRoute.of(context).settings.arguments;<br>}<br></code></pre></td></tr></table></figure><ul><li>只能使用路由表传参</li></ul><figure class="highlight reasonml"><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></pre></td><td class="code"><pre><code class="hljs reasonml"><span class="hljs-comment">// 第二种路由方式</span><br><span class="hljs-comment">// 先注册路由表</span><br>routes: {<br> <span class="hljs-string">"ParamsRoute"</span>: (context) {<br> return <span class="hljs-constructor">ParamsRoute(<span class="hljs-params">params</span>: ModalRoute.<span class="hljs-params">of</span>(<span class="hljs-params">context</span>)</span>.settings.arguments);<br> },<br>}<br><br><span class="hljs-comment">// 传参调用方法</span><br>onPressed: <span class="hljs-literal">()</span> async {<br> var backparams = await <span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">Navigator</span>.</span></span><span class="hljs-keyword">of</span>(context).push<span class="hljs-constructor">Named(<span class="hljs-string">"ParamsRoute"</span>, <span class="hljs-params">arguments</span>: <span class="hljs-string">""</span>)</span>;<br> print(backparams);<br>}<br></code></pre></td></tr></table></figure><h4 id="2、未注册路由表键值对"><a href="#2、未注册路由表键值对" class="headerlink" title="2、未注册路由表键值对"></a>2、未注册路由表键值对</h4><ul><li>如果没有在路由表中找到,那么会触发<code>onGenerateRoute</code>方法,此方法中会获取到触发的命名路由的名称,在此方法内生成新的路由地址返回即可</li><li>官方建议使用命名路由,使用<code>onGenerateRoute</code>统一入口</li></ul><figure class="highlight typescript"><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><code class="hljs typescript"><span class="hljs-meta">@override</span><br>Wid<span class="hljs-keyword">get</span> <span class="hljs-title">build</span>(<span class="hljs-params">BuildContext context</span>) {<br> <span class="hljs-keyword">return</span> MaterialApp(<br> onGenerateRoute: (RouteSettings settings) {<br> WidgetBuilder builder;<br> <span class="hljs-keyword">if</span> (settings.name == <span class="hljs-string">'NewPageRoute'</span>) {<br> builder = <span class="hljs-function">(<span class="hljs-params">BuildContext context</span>) =></span> NewPageRoute();<br> } <span class="hljs-keyword">else</span> {<br> print(<span class="hljs-string">"没有对应的页面"</span>);<br> }<br> <span class="hljs-keyword">return</span> MaterialPageRoute(builder: builder, <span class="hljs-attr">settings</span>: settings);<br> }<br> );<br>}<br></code></pre></td></tr></table></figure><p>以上代码如下:</p><figure class="highlight scala"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br></pre></td><td class="code"><pre><code class="hljs scala"><span class="hljs-keyword">import</span> <span class="hljs-symbol">'package</span>:flutter/material.dart';<br><br>void main() => runApp(<span class="hljs-type">MyApp</span>());<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-comment">// This widget is the root of your application.</span><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">MaterialApp</span>(<br> title: <span class="hljs-symbol">'Flutter</span> <span class="hljs-type">Demo</span>',<br> theme: <span class="hljs-type">ThemeData</span>(<br> primarySwatch: <span class="hljs-type">Colors</span>.blue,<br> ),<br> <span class="hljs-comment">// home: MyHomePage(title: 'Flutter Demo Home Page'),</span><br><br> initialRoute: <span class="hljs-string">"homeRoute"</span>,<br> <span class="hljs-comment">//注册路由表</span><br> routes: {<br> <span class="hljs-string">"homeRoute"</span>: (context) => <span class="hljs-type">MyHomePage</span>(title: <span class="hljs-string">"Flutter Demo Home Page"</span>),<br> <span class="hljs-string">"newpage1"</span>: (context) => <span class="hljs-type">NewRoute</span>(),<br> <span class="hljs-string">"newpage2"</span>: (context) => <span class="hljs-type">EchoRoute</span>(),<br> <span class="hljs-string">"newpage23"</span>: (context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">TipRoute</span>(tip: <span class="hljs-type">ModalRoute</span>.of(context).settings.arguments);<br> },<br> <span class="hljs-string">"newpage4"</span>: (context) => <span class="hljs-type">ForthPage</span>(),<br> },<br> onGenerateRoute: (<span class="hljs-type">RouteSettings</span> settings) {<br> <span class="hljs-type">WidgetBuilder</span> builder;<br> <span class="hljs-keyword">if</span> (settings.name == <span class="hljs-symbol">'newpage</span>5') {<br> builder = (<span class="hljs-type">BuildContext</span> context) => <span class="hljs-type">FifthPage</span>();<br> } <span class="hljs-keyword">else</span> {<br> print(<span class="hljs-string">"没有对应的页面"</span>);<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-type">MaterialPageRoute</span>(builder: builder, settings: settings);<br> },<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyHomePage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> <span class="hljs-type">MyHomePage</span>({<span class="hljs-type">Key</span> key, <span class="hljs-keyword">this</span>.title}) : <span class="hljs-keyword">super</span>(key: key);<br> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> title;<br><br> <span class="hljs-meta">@override</span><br> _MyHomePageState createState() => _MyHomePageState();<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_MyHomePageState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<MyHomePage></span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(widget.title),<br> ),<br> body: <span class="hljs-type">Center</span>(<br> child: <span class="hljs-type">Column</span>(<br> mainAxisAlignment: <span class="hljs-type">MainAxisAlignment</span>.center,<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">FlatButton</span>(<br> color: <span class="hljs-type">Colors</span>.blue,<br> textColor: <span class="hljs-type">Colors</span>.white,<br> child: <span class="hljs-type">Text</span>(<br> <span class="hljs-string">"open first new page"</span>,<br> ),<br> onPressed: () {<br> <span class="hljs-type">Navigator</span>.pushNamed(context, <span class="hljs-string">"newpage1"</span>);<br> },<br> ),<br> <span class="hljs-type">FlatButton</span>(<br> color: <span class="hljs-type">Colors</span>.blue,<br> textColor: <span class="hljs-type">Colors</span>.white,<br> child: <span class="hljs-type">Text</span>(<br> <span class="hljs-string">"open second new page"</span>,<br> ),<br> onPressed: () {<br> <span class="hljs-type">Navigator</span>.of(context).pushNamed(<span class="hljs-string">"newpage2"</span>, arguments: <span class="hljs-string">"hi"</span>);<br> },<br> ),<br> <span class="hljs-type">FlatButton</span>(<br> color: <span class="hljs-type">Colors</span>.blue,<br> textColor: <span class="hljs-type">Colors</span>.white,<br> child: <span class="hljs-type">Text</span>(<br> <span class="hljs-string">"open third new page"</span>,<br> ),<br> onPressed: () async {<br> <span class="hljs-keyword">var</span> backparams = await <span class="hljs-type">Navigator</span>.push(context,<br> <span class="hljs-type">MaterialPageRoute</span>(builder: (newpage) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">TipRoute</span>(tip: <span class="hljs-string">"333"</span>);<br> }));<br> print(backparams);<br> },<br> ),<br> <span class="hljs-type">FlatButton</span>(<br> color: <span class="hljs-type">Colors</span>.blue,<br> textColor: <span class="hljs-type">Colors</span>.white,<br> child: <span class="hljs-type">Text</span>(<br> <span class="hljs-string">"open third new page2"</span>,<br> ),<br> onPressed: () async {<br> <span class="hljs-keyword">var</span> backparams = await <span class="hljs-type">Navigator</span>.of(context).pushNamed(<span class="hljs-string">"newpage23"</span>, arguments: <span class="hljs-string">"2233"</span>);<br> print(backparams);<br> },<br> ),<br> <span class="hljs-type">FlatButton</span>(<br> color: <span class="hljs-type">Colors</span>.blue,<br> textColor: <span class="hljs-type">Colors</span>.white,<br> child: <span class="hljs-type">Text</span>(<br> <span class="hljs-string">"open third new page4"</span>,<br> ),<br> onPressed: () async {<br> <span class="hljs-keyword">var</span> backparams = await <span class="hljs-type">Navigator</span>.of(context).pushNamed(<span class="hljs-string">"newpage4"</span>, arguments: <span class="hljs-string">"4444"</span>);<br> print(backparams);<br> },<br> ),<br> <span class="hljs-type">FlatButton</span>(<br> color: <span class="hljs-type">Colors</span>.blue,<br> textColor: <span class="hljs-type">Colors</span>.white,<br> child: <span class="hljs-type">Text</span>(<br> <span class="hljs-string">"open third new page5"</span>,<br> ),<br> onPressed: () async {<br> <span class="hljs-keyword">var</span> backparams = await <span class="hljs-type">Navigator</span>.of(context).pushNamed(<span class="hljs-string">"newpage5"</span>, arguments: <span class="hljs-string">"5555"</span>);<br> print(backparams);<br> },<br> ),<br> <span class="hljs-type">FlatButton</span>(<br> color: <span class="hljs-type">Colors</span>.blue,<br> textColor: <span class="hljs-type">Colors</span>.white,<br> child: <span class="hljs-type">Text</span>(<br> <span class="hljs-string">"open third new page6"</span>,<br> ),<br> onPressed: () {<br> <span class="hljs-type">Navigator</span>.of(context).pushNamed(<span class="hljs-string">"newpage6"</span>, arguments: <span class="hljs-string">"6666"</span>);<br> },<br> ),<br> ],<br> ),<br> ),<br> <span class="hljs-comment">// This trailing comma makes auto-formatting nicer for build methods.</span><br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NewRoute</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(<span class="hljs-string">"new page"</span>),<br> ),<br> body: <span class="hljs-literal">null</span>,<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EchoRoute</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">var</span> args = <span class="hljs-type">ModalRoute</span>.of(context).settings.arguments;<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(<span class="hljs-string">"new page2EchoRoute"</span>),<br> ),<br> body: <span class="hljs-type">Text</span>(args),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TipRoute</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-type">TipRoute</span>({<span class="hljs-type">Key</span> key, <span class="hljs-meta">@required</span> <span class="hljs-keyword">this</span>.tip}) : <span class="hljs-keyword">super</span>(key: key);<br> <span class="hljs-keyword">final</span> tip;<br><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(<span class="hljs-string">"new page3TipRoute"</span>),<br> ),<br> body: <span class="hljs-type">Column</span>(<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">Text</span>(tip),<br> <span class="hljs-type">FlatButton</span>(<br> color: <span class="hljs-type">Colors</span>.blue,<br> textColor: <span class="hljs-type">Colors</span>.white,<br> child: <span class="hljs-type">Text</span>(<br> <span class="hljs-string">"back and send params"</span>,<br> ),<br> onPressed: () {<br> <span class="hljs-type">Navigator</span>.pop(context, tip);<br> },<br> ),<br> ],<br> ),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ForthPage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">var</span> args = <span class="hljs-type">ModalRoute</span>.of(context).settings.arguments;<br><br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(<span class="hljs-string">"第四个页面"</span>),<br> ),<br> body: <span class="hljs-type">Column</span>(<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">Text</span>(args),<br> <span class="hljs-type">FlatButton</span>(<br> child: <span class="hljs-type">Text</span>(<span class="hljs-string">"back and send params"</span>),<br> color: <span class="hljs-type">Colors</span>.blue,<br> textColor: <span class="hljs-type">Colors</span>.white,<br> onPressed: () {<br> <span class="hljs-type">Navigator</span>.pop(context, args);<br> },<br> ),<br> ],<br> ),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FifthPage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">var</span> args = <span class="hljs-type">ModalRoute</span>.of(context).settings.arguments;<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(<span class="hljs-string">"第五个页面"</span>),<br> ),<br> body: <span class="hljs-type">Column</span>(<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">Text</span>(args),<br> <span class="hljs-type">FlatButton</span>(<br> child: <span class="hljs-type">Text</span>(<span class="hljs-string">"back and send params"</span>),<br> color: <span class="hljs-type">Colors</span>.blue,<br> textColor: <span class="hljs-type">Colors</span>.white,<br> onPressed: () {<br> <span class="hljs-type">Navigator</span>.pop(context, args);<br> },<br> ),<br> ],<br> ),<br> );<br> }<br>}<br><br></code></pre></td></tr></table></figure><h3 id="四、包管理"><a href="#四、包管理" class="headerlink" title="四、包管理"></a>四、包管理</h3><ul><li><code>pubspec.yaml</code>文件</li><li><a href="https://pub.dev/"><code>Pub</code>仓库</a>,类似于<code>node</code>中的<code>npm</code>仓库</li><li><code>VS Code</code>中可以直接编辑<code>pubspec.yaml</code>文件,每次修改保存后,会自动触发<code>flutter packages get</code>方法,也可以使用命令行手动触发</li><li>需要注意<code>dependencies</code>和<code>dev_dependencies</code>的区别,前者的依赖包将作为<code>APP</code>的源码的一部分参与编译,生成最终的安装包。而后者的依赖包只是作为开发阶段的一些工具包,主要是用于帮助我们提高开发、测试效率,比如<code>flutter</code>的自动化测试包</li></ul><h3 id="四、资源管理和调试工具"><a href="#四、资源管理和调试工具" class="headerlink" title="四、资源管理和调试工具"></a>四、资源管理和调试工具</h3><ul><li>资源管理</li><li><code>flutter</code>调试<ul><li><code>print</code>和<code>debugPrint</code>都可以打印,建议使用<code>debugPrint</code>,避免输出内容过多时<code>Android</code>丢失部分内容</li><li><code>debugDumpApp</code>输出<code>Widgets</code>树</li><li><code>debugDumpRenderTree</code>输出渲染树</li><li><code>debugDumpLayerTree</code>输出<code>Layer</code>树</li><li><code>debugDumpSemanticsTree</code>输出语义树</li></ul></li><li>统计应用启动时间<ul><li><code>$ flutter run --trace-startup --profile</code>,结果保存到<code>build</code>目录下<code>start_up_info.json</code>文件</li></ul></li></ul><h3 id="五、State生命周期"><a href="#五、State生命周期" class="headerlink" title="五、State生命周期"></a>五、<code>State</code>生命周期</h3><p><img src="image_1.png" alt="image_1"></p><h3 id="六、组件库"><a href="#六、组件库" class="headerlink" title="六、组件库"></a>六、组件库</h3><ul><li><code>iOS Cupertino</code>风格 </li><li><code>Android Material</code>风格</li></ul><h4 id="1、基础组件"><a href="#1、基础组件" class="headerlink" title="1、基础组件"></a>1、基础组件</h4><ul><li><code>Text</code>:该组件可让您创建一个带格式的文本。</li><li><code>Row</code>、<code>Column</code>: 这些具有弹性空间的布局类<code>Widget</code>可让您在水平(<code>Row</code>)和垂直(<code>Column</code>)方向上创建灵活的布局。其设计是基于<code>Web</code>开发中的<code>Flexbox</code>布局模型。</li><li><code>Stack</code>: 取代线性布局,<code>Stack</code>允许子<code>widget</code>堆叠, 你可以使用<code>Positioned</code>来定位他们相对于<code>Stack</code>的上下左右四条边的位置。<code>Stacks</code>是基于<code>Web</code>开发中的绝对定位(<code>absolute positioning</code>)布局模型设计的。</li><li><code>Container</code>:<code>Container</code>可让您创建矩形视觉元素。<code>container</code> 可以装饰一个<code>BoxDecoration</code>, 如 <code>background</code>、一个边框、或者一个阴影。<code>Container</code>也可以具有边距(<code>margins</code>)、填充(<code>padding</code>)和应用于其大小的约束(<code>constraints</code>)。另外,<code>Container</code>可以使用矩阵在三维空间中对其进行变换</li></ul><h4 id="2、Material组件"><a href="#2、Material组件" class="headerlink" title="2、Material组件"></a>2、<code>Material</code>组件</h4><ul><li><code>MaterialApp</code>、<code>Scaffold</code>、<code>AppBar</code>、<code>FlatButton</code>等</li><li>初始页面推荐使用<code>MaterialApp</code></li></ul><h3 id="七、状态管理"><a href="#七、状态管理" class="headerlink" title="七、状态管理"></a>七、状态管理</h3><ul><li>如果状态是用户数据,如复选框的选中状态、滑块的位置,则该状态最好由父<code>Widget</code>管理</li><li>如果状态是有关界面外观效果的,例如颜色、动画,那么状态最好由<code>Widget</code>本身来管理</li><li>如果某一个状态是不同Widget共享的则最好由它们共同的父<code>Widget</code>管理</li></ul><figure class="highlight scala"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br></pre></td><td class="code"><pre><code class="hljs scala"><span class="hljs-keyword">import</span> <span class="hljs-symbol">'package</span>:flutter/material.dart';<br><br>void main() => runApp(<span class="hljs-type">MyApp</span>());<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">MaterialApp</span>(<br> title: <span class="hljs-symbol">'Flutter</span> <span class="hljs-type">Demo</span>',<br> theme: <span class="hljs-type">ThemeData</span>(<br> primarySwatch: <span class="hljs-type">Colors</span>.blue,<br> ),<br> home: <span class="hljs-type">MyHomePage</span>(title: <span class="hljs-symbol">'Flutter</span> <span class="hljs-type">Demo</span> <span class="hljs-type">Home</span> <span class="hljs-type">Page</span>'),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyHomePage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> <span class="hljs-type">MyHomePage</span>({<span class="hljs-type">Key</span> key, <span class="hljs-keyword">this</span>.title}) : <span class="hljs-keyword">super</span>(key: key);<br> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> title;<br> <span class="hljs-meta">@override</span><br> _MyHomePageState createState() => _MyHomePageState();<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_MyHomePageState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<MyHomePage></span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(widget.title),<br> ),<br> body: <span class="hljs-type">Row</span>(<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">TapboxA</span>(),<br> <span class="hljs-type">ParentWidget</span>(),<br> ],<br> ),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TapboxA</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> _TapboxAState createState() => <span class="hljs-keyword">new</span> _TapboxAState();<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_TapboxAState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<TapboxA></span> </span>{<br> bool _selected = <span class="hljs-literal">true</span>;<br> void _refreshSeleced() {<br> setState(() {<br> _selected = !_selected;<br> });<br> }<br><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Container</span>(<br> width: <span class="hljs-number">200</span>,<br> height: <span class="hljs-number">200</span>,<br> padding: <span class="hljs-type">EdgeInsets</span>.all(<span class="hljs-number">5</span>),<br> color: <span class="hljs-type">Colors</span>.orange,<br> child: <span class="hljs-type">FlatButton</span>(<br> child: <span class="hljs-type">Text</span>(<br> _selected ? <span class="hljs-symbol">'0</span>0' : <span class="hljs-symbol">'9</span>9',<br> style: <span class="hljs-type">TextStyle</span>(<br> fontSize: <span class="hljs-number">40</span>,<br> color: <span class="hljs-type">Colors</span>.white,<br> ),<br> ),<br> color: _selected ? <span class="hljs-type">Colors</span>.blue : <span class="hljs-type">Colors</span>.red,<br> onPressed: () {<br> _refreshSeleced();<br> },<br> ),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ParentWidget</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> _ParentWidgetState createState() => <span class="hljs-keyword">new</span> _ParentWidgetState();<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">_ParentWidgetState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<ParentWidget></span> </span>{<br> bool _selected = <span class="hljs-literal">true</span>;<br> void _refreshSeleced(bool selected) {<br> setState(() {<br> _selected = selected;<br> });<br> }<br><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">TapboxB</span>(<br> selected: _selected,<br> selectedValueChanged: _refreshSeleced,<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TapboxB</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-keyword">final</span> bool selected;<br> <span class="hljs-keyword">final</span> <span class="hljs-type">ValueChanged</span><bool> selectedValueChanged;<br><br> <span class="hljs-type">TapboxB</span>({<br> <span class="hljs-type">Key</span> key,<br> <span class="hljs-keyword">this</span>.selected,<br> <span class="hljs-keyword">this</span>.selectedValueChanged,<br> }):<span class="hljs-keyword">super</span>(key: key);<br> <br> void _refreshSelecedB() {<br> selectedValueChanged(!selected);<br> }<br><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Container</span>(<br> width: <span class="hljs-number">200</span>,<br> height: <span class="hljs-number">200</span>,<br> padding: <span class="hljs-type">EdgeInsets</span>.all(<span class="hljs-number">5</span>),<br> color: <span class="hljs-type">Colors</span>.orange,<br> child: <span class="hljs-type">FlatButton</span>(<br> child: <span class="hljs-type">Text</span>(<br> selected ? <span class="hljs-symbol">'0</span>0' : <span class="hljs-symbol">'9</span>9',<br> style: <span class="hljs-type">TextStyle</span>(<br> fontSize: <span class="hljs-number">40</span>,<br> color: <span class="hljs-type">Colors</span>.white,<br> ),<br> ),<br> color: selected ? <span class="hljs-type">Colors</span>.blue : <span class="hljs-type">Colors</span>.red,<br> onPressed: () {<br> _refreshSelecedB();<br> },<br> ),<br> );<br> }<br>}<br><br></code></pre></td></tr></table></figure><p><span style="color: lightgray;"><em>未完待续</em></span></p>]]></content>
<categories>
<category>flutter</category>
</categories>
<tags>
<tag>flutter</tag>
<tag>学习日记</tag>
</tags>
</entry>
<entry>
<title>Flutter学习日记-log1</title>
<link href="/2020/03/04/Flutter%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log1/"/>
<url>/2020/03/04/Flutter%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log1/</url>
<content type="html"><![CDATA[<blockquote><p><em>入职了新公司,终于接触到了Flutter,在此记录每天上手成果</em></p></blockquote><blockquote><p><a href="https://flutterchina.club/get-started/install/"><em>Flutter中文网</em></a></p></blockquote><hr><h2 id="日志随笔"><a href="#日志随笔" class="headerlink" title="日志随笔"></a>日志随笔</h2><h3 id="一、Flutter环境搭建"><a href="#一、Flutter环境搭建" class="headerlink" title="一、Flutter环境搭建"></a>一、<code>Flutter</code>环境搭建</h3><p>直接参考<a href="https://flutterchina.club/get-started/install/"><code>Flutter</code>中文网</a>,进行部署,最后使用<code>flutter doctor</code>命令行校验,本机环境如下:</p><figure class="highlight pgsql"><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></pre></td><td class="code"><pre><code class="hljs pgsql">$ flutter doctor<br>Doctor <span class="hljs-keyword">summary</span> (<span class="hljs-keyword">to</span> see <span class="hljs-keyword">all</span> details, run flutter doctor -v):<br>[✓] Flutter (Channel <span class="hljs-keyword">stable</span>, v1<span class="hljs-number">.12</span><span class="hljs-number">.13</span>, <span class="hljs-keyword">on</span> Mac OS X <span class="hljs-number">10.14</span><span class="hljs-number">.4</span> <span class="hljs-number">18E226</span>, locale<br> zh-Hans-CN)<br> <br>[✓] Android toolchain - develop <span class="hljs-keyword">for</span> Android devices (Android SDK <span class="hljs-keyword">version</span> <span class="hljs-number">29.0</span><span class="hljs-number">.2</span>)<br>[✓] Xcode - develop <span class="hljs-keyword">for</span> iOS <span class="hljs-keyword">and</span> macOS (Xcode <span class="hljs-number">11.3</span><span class="hljs-number">.1</span>)<br>[✓] Android Studio (<span class="hljs-keyword">version</span> <span class="hljs-number">3.5</span>)<br>[✓] VS Code (<span class="hljs-keyword">version</span> <span class="hljs-number">1.42</span><span class="hljs-number">.1</span>)<br>[✓] Connected device (<span class="hljs-number">2</span> available)<br><br>• <span class="hljs-keyword">No</span> issues <span class="hljs-built_in">found</span>!<br></code></pre></td></tr></table></figure><p>本机采用<code>VS Code</code>编辑器进行编辑,按照文档下载对应的插件即可</p><h3 id="二、创建初始代码"><a href="#二、创建初始代码" class="headerlink" title="二、创建初始代码"></a>二、创建初始代码</h3><p>使用<code>VS Code</code>中的命令创建默认<code>demo</code>,层级如下:</p><p><img src="image_1.png" alt="image_1"></p><p>其中<code>ios</code>文件夹中的代码即为<code>Xcode</code>工程,可以使用<code>Xcode</code>打开运行即可,测试发现一个<span style="color: red;">问题:<code>iOS</code>模拟器运行正常,但是使用真机运行失败,<code>github</code>上解答:<code>iOS 13.3.1</code>真机存在免费账号签名问题,无法运行,只能使用<code>iOS</code>模拟器运行</span></p><h3 id="三、初始Demo解析"><a href="#三、初始Demo解析" class="headerlink" title="三、初始Demo解析"></a>三、初始<code>Demo</code>解析</h3><h4 id="1、main函数启动程序"><a href="#1、main函数启动程序" class="headerlink" title="1、main函数启动程序"></a>1、<code>main</code>函数启动程序</h4><ul><li>初始<code>widget</code>需要使用<code>MaterialApp</code>创建,常见参数:<code>title</code>、<code>theme</code>、<code>home</code>,其中<code>home</code>参数认为是必填参数,代表首页</li></ul><h4 id="2、StatefulWidget和StatelessWidget"><a href="#2、StatefulWidget和StatelessWidget" class="headerlink" title="2、StatefulWidget和StatelessWidget"></a>2、<code>StatefulWidget</code>和<code>StatelessWidget</code></h4><ul><li><code>StatefulWidget</code>是动态,<code>StatelessWidget</code>是静态</li><li>都需要重写<code>build</code>方法,</li><li>优先使用<code>StatelessWidget</code></li></ul><p>具体内部实现区别,暂不研究</p><h4 id="3、监听动态StatefulWidget的状态改变"><a href="#3、监听动态StatefulWidget的状态改变" class="headerlink" title="3、监听动态StatefulWidget的状态改变"></a>3、监听动态<code>StatefulWidget</code>的状态改变</h4><blockquote><p>创建一个<code>State</code>类,绑定到<code>StatefulWidget</code>,同时在<code>StatefulWidget</code>中使用<code>createState</code>方法添加<code>State</code>类,然后把重写<code>build</code>方法的代码写在<code>State</code>里面,在事件触发时,掉用<code>setState</code>方法,此时会重新执行<code>StatefulWidget</code>的<code>build</code>方法,此处需注意,不是所有代码都会执行</p></blockquote><h4 id="4、使用Navigator打开新的页面"><a href="#4、使用Navigator打开新的页面" class="headerlink" title="4、使用Navigator打开新的页面"></a>4、使用<code>Navigator</code>打开新的页面</h4><ul><li>新的页面,不代表是新的<code>dart</code>文件,新页面仍然可以在同一个<code>dart</code>里面创建出来</li><li><code>Navigator.push</code>有两个参数,第一个是默认值<code>content</code>,此处暂不做验证</li><li>第二个值是新页面,新页面需要使用<code>MaterialPageRoute</code>方法创建出来,此方法参数<code>builder</code>必填,括号内形参,方法内<code>return</code>新的页面,就能给形参赋值,从而正常跳转</li></ul><p>以上所有代码如下:</p><figure class="highlight scala"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br></pre></td><td class="code"><pre><code class="hljs scala"><span class="hljs-keyword">import</span> <span class="hljs-symbol">'package</span>:flutter/material.dart';<br><br>void main() => runApp(<span class="hljs-type">MyApp</span>());<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">MaterialApp</span>(<br> title: <span class="hljs-string">"aaa"</span>,<br> theme: <span class="hljs-type">ThemeData</span>(<br> primarySwatch: <span class="hljs-type">Colors</span>.blue,<br> ),<br> home: <span class="hljs-type">HomePage</span>(),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HomePage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatefulWidget</span> </span>{<br> <span class="hljs-type">HomePageState</span> createState() => <span class="hljs-keyword">new</span> <span class="hljs-type">HomePageState</span>();<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HomePageState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">State<HomePage></span> </span>{<br> <span class="hljs-keyword">var</span> count = <span class="hljs-number">0</span>;<br> void countup() {<br> count++;<br> setState(() {<br> print(<span class="hljs-string">"jjj"</span>);<br> nslog(<span class="hljs-string">"kkk"</span>);<br> });<br> }<br><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(<span class="hljs-string">"bbb"</span>),<br> ),<br> body: <span class="hljs-type">Center</span>(<br> child: <span class="hljs-type">Column</span>(<br> mainAxisAlignment: <span class="hljs-type">MainAxisAlignment</span>.center,<br> children: [<br> <span class="hljs-type">Text</span>(<span class="hljs-string">"ccc"</span>),<br> <span class="hljs-type">Text</span>(<br> <span class="hljs-string">"$count"</span>,<br> ),<br> <span class="hljs-type">FlatButton</span>(<br> child: <span class="hljs-type">Text</span>(<span class="hljs-string">"ddd"</span>),<br> textColor: <span class="hljs-type">Colors</span>.blue,<br> onPressed: () {<br> print(<span class="hljs-string">"eee"</span>);<br> <span class="hljs-type">Navigator</span>.push(context, <span class="hljs-type">MaterialPageRoute</span>(builder: (newpage) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">NewPage</span>();<br> }));<br> },<br> onLongPress: () {<br> print(<span class="hljs-string">"iii"</span>);<br> },<br> ),<br> ],<br> ),<br> ),<br> floatingActionButton: <span class="hljs-type">FloatingActionButton</span>(<br> onPressed: () {<br> print(<span class="hljs-string">"hhh"</span>);<br> countup();<br> },<br> <span class="hljs-comment">// tooltip: 'Increment',</span><br> child: <span class="hljs-type">Icon</span>(<span class="hljs-type">Icons</span>.add),<br> ),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NewPage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(<span class="hljs-string">"fff"</span>),<br> ),<br> body: <span class="hljs-type">Center</span>(<br> child: <span class="hljs-type">Text</span>(<span class="hljs-string">"ggg"</span>),<br> ),<br> );<br> }<br>}<br><br>void nslog(<span class="hljs-type">String</span> string) {<br> print(string);<br>}<br><br></code></pre></td></tr></table></figure><h3 id="四、路由传参"><a href="#四、路由传参" class="headerlink" title="四、路由传参"></a>四、路由传参</h3><ul><li>有固定的格式,接收参数的<code>widget</code>通过固定语法接收参数,接收完之后定义一个参数存储,传输过程中参数名相同</li><li>回调的参数使用打开<code>widget</code>的方法回调,<code>Navigator.push</code>对应<code>Navigator.pop</code>,同样,第二个参数为回调参数</li><li>第一个<code>widget</code>获取回调参数时,需要使用<code>await</code>修饰,才能获取到回调参数,传参方法中也可以使用<code>async</code>异步修饰</li><li><code>async</code>和<code>await</code>分别代表异步操作和延迟操作</li></ul><p>代码如下:</p><figure class="highlight scala"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><code class="hljs scala"><span class="hljs-keyword">import</span> <span class="hljs-symbol">'package</span>:flutter/material.dart';<br><br>void main() => runApp(<span class="hljs-type">MyApp</span>());<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-comment">// This widget is the root of your application.</span><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">MaterialApp</span>(<br> title: <span class="hljs-symbol">'Route</span> <span class="hljs-type">Params</span>',<br> theme: <span class="hljs-type">ThemeData</span>(<br> primarySwatch: <span class="hljs-type">Colors</span>.blue,<br> ),<br> home: <span class="hljs-type">MyHomePage</span>(),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyHomePage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(<span class="hljs-string">"111"</span>),<br> ),<br> body: <span class="hljs-type">Column</span>(<br> children: [<br> <span class="hljs-type">Text</span>(<span class="hljs-string">"222"</span>),<br> <span class="hljs-type">FlatButton</span>(<br> child: <span class="hljs-type">Text</span>(<span class="hljs-string">"333"</span>),<br> color: <span class="hljs-type">Colors</span>.blue,<br> onPressed: () async {<br> <span class="hljs-keyword">var</span> backParams = await <span class="hljs-type">Navigator</span>.push(context, <br> <span class="hljs-type">MaterialPageRoute</span>(builder: (newpage) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">TipRoute</span>(text: <span class="hljs-string">"444"</span>);<br> })<br> );<br> print(<span class="hljs-string">"返回值"</span>+<span class="hljs-string">"$backParams"</span>);<br> },<br> )<br> ],<br> ),<br> );<br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TipRoute</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{<br> <span class="hljs-type">TipRoute</span>({<br> <span class="hljs-type">Key</span> key,<br> <span class="hljs-meta">@required</span> <span class="hljs-keyword">this</span>.text, <span class="hljs-comment">// 接收一个text参数</span><br> }) : <span class="hljs-keyword">super</span>(key: key);<br> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> text;<br><br> <span class="hljs-meta">@override</span><br> <span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {<br> <span class="hljs-keyword">return</span> <span class="hljs-type">Scaffold</span>(<br> appBar: <span class="hljs-type">AppBar</span>(<br> title: <span class="hljs-type">Text</span>(<span class="hljs-string">"提示"</span>),<br> ),<br> body: <span class="hljs-type">Padding</span>(<br> padding: <span class="hljs-type">EdgeInsets</span>.all(<span class="hljs-number">18</span>),<br> child: <span class="hljs-type">Center</span>(<br> child: <span class="hljs-type">Column</span>(<br> children: <<span class="hljs-type">Widget</span>>[<br> <span class="hljs-type">Text</span>(text),<br> <span class="hljs-type">RaisedButton</span>(<br> onPressed: () => <span class="hljs-type">Navigator</span>.pop(context, <span class="hljs-string">"我是返回值"</span>),<br> child: <span class="hljs-type">Text</span>(<span class="hljs-string">"返回"</span>),<br> )<br> ],<br> ),<br> ),<br> ),<br> );<br> }<br>}<br><br></code></pre></td></tr></table></figure><p><span style="color: lightgray;"><em>未完待续</em></span></p>]]></content>
<categories>
<category>flutter</category>
</categories>
<tags>
<tag>flutter</tag>
<tag>学习日记</tag>
</tags>
</entry>
<entry>
<title>启用hexo新主题indigo</title>
<link href="/2020/02/26/%E5%90%AF%E7%94%A8hexo%E6%96%B0%E4%B8%BB%E9%A2%98indigo/"/>
<url>/2020/02/26/%E5%90%AF%E7%94%A8hexo%E6%96%B0%E4%B8%BB%E9%A2%98indigo/</url>
<content type="html"><![CDATA[<p>我的博客原来的主题是<a href="https://github.com/forsigner/fexo"><code>fexo</code></a>,经过了一段时间后,也有点审美疲劳了,所以本次切换主题到<a href="https://github.com/yscoder/hexo-theme-indigo"><code>hexo-theme-indigo</code></a></p><h3 id="一、部分个性化"><a href="#一、部分个性化" class="headerlink" title="一、部分个性化"></a>一、部分个性化</h3><p>部署完该主题后,我觉的有部分内容需要修改为我自己的风格,所以做了如下修改</p><h4 id="1、左上部分头像、姓名和邮箱位置居中"><a href="#1、左上部分头像、姓名和邮箱位置居中" class="headerlink" title="1、左上部分头像、姓名和邮箱位置居中"></a>1、左上部分头像、姓名和邮箱位置居中</h4><ul><li><code>/indigo/layout/_partial/menu.ejs</code></li></ul><figure class="highlight xml"><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><code class="hljs xml"><span class="hljs-comment"><!--第7行,添加居中样式--></span><br><span class="hljs-comment"><!--<div class="brand">--></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"brand"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"text-align: center;"</span>></span><br></code></pre></td></tr></table></figure><figure class="highlight xml"><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><code class="hljs xml"><span class="hljs-comment"><!--第8行,添加居中样式--></span><br><span class="hljs-comment"><!--<a href="<%- url_for(theme.avatar_link) %>" class="avatar waves-effect waves-circle waves-light">--></span><br><span class="hljs-tag"><<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"<%- url_for(theme.avatar_link) %>"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"avatar waves-effect waves-circle waves-light"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"margin-left: 60px;"</span>></span><br></code></pre></td></tr></table></figure><h4 id="2、隐藏底部关于版权的内容,并把RSS按钮改到最底部"><a href="#2、隐藏底部关于版权的内容,并把RSS按钮改到最底部" class="headerlink" title="2、隐藏底部关于版权的内容,并把RSS按钮改到最底部"></a>2、隐藏底部关于版权的内容,并把<code>RSS</code>按钮改到最底部</h4><ul><li><code>/themes/indigo/layout/_partial/footer.ejs</code></li></ul><figure class="highlight vbscript-html"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs vbscript-html"><span class="xml"><span class="hljs-tag"><<span class="hljs-name">footer</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"footer"</span>></span></span><br><span class="xml"> <span class="hljs-comment"><!--删除上半部分标签--></span></span><br><span class="xml"> <span class="hljs-comment"><!--<div class="top">--></span></span><br><span class="xml"> <span class="hljs-comment"><!-- </span></span><span class="vbscript"><%- partial(<span class="hljs-comment">'plugins/site-visit') %></span></span><span class="xml"><span class="hljs-comment">--></span></span><br><span class="xml"> <span class="hljs-comment"><!-- <p>--></span></span><br><span class="xml"> <span class="hljs-comment"><!-- </span></span><span class="vbscript"><% <span class="hljs-keyword">if</span> ((config.feed) && (config.feed.path.length)) { %></span><span class="xml"><span class="hljs-comment">--></span></span><br><span class="xml"> <span class="hljs-comment"><!-- <span><a href="</span></span><span class="vbscript"><%- url_for(config.feed.path) %></span><span class="xml"><span class="hljs-comment">" target="_blank" class="rss" title="rss"><i class="icon icon-lg icon-rss"></i></a></span>--></span></span><br><span class="xml"> <span class="hljs-comment"><!-- </span></span><span class="vbscript"><% } %></span><span class="xml"><span class="hljs-comment">--></span></span><br><span class="xml"> <span class="hljs-comment"><!-- <span></span></span><span class="vbscript"><%- __(<span class="hljs-comment">'footer.license') %></span></span><span class="xml"><span class="hljs-comment"></span>--></span></span><br><span class="xml"> <span class="hljs-comment"><!-- </p>--></span></span><br><span class="xml"> <span class="hljs-comment"><!--</div>--></span></span><br><span class="xml"> <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bottom"</span>></span></span><br><span class="xml"> <span class="hljs-tag"><<span class="hljs-name">p</span>></span><span class="hljs-tag"><<span class="hljs-name">span</span>></span></span><span class="vbscript"><%-config.author %></span><span class="xml"> <span class="hljs-symbol">&copy;</span> </span><span class="vbscript"><%<span class="hljs-keyword">if</span> (theme.since_year && theme.since_year < <span class="hljs-built_in">date</span>(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(), <span class="hljs-comment">'YYYY')) {%></span></span><span class="vbscript"><%- theme.since_year %></span><span class="xml"> - </span><span class="vbscript"><%}%></span><span class="vbscript"><%- <span class="hljs-built_in">date</span>(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(), <span class="hljs-comment">'YYYY') %></span></span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span><br><span class="xml"> </span><br><span class="xml"> <span class="hljs-comment"><!--添加RSS标签--></span></span><br><span class="xml"> </span><span class="vbscript"><% <span class="hljs-keyword">if</span> ((config.feed) && (config.feed.path.length)) { %></span><br><span class="xml"> <span class="hljs-tag"><<span class="hljs-name">span</span>></span><span class="hljs-tag"><<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"</span></span></span><span class="vbscript"><%- url_for(config.feed.path) %></span><span class="xml"><span class="hljs-tag"><span class="hljs-string">"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"rss"</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"rss"</span>></span><span class="hljs-tag"><<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icon icon-lg icon-rss"</span>></span><span class="hljs-tag"></<span class="hljs-name">i</span>></span><span class="hljs-tag"></<span class="hljs-name">a</span>></span><span class="hljs-tag"></<span class="hljs-name">span</span>></span></span><br><span class="xml"> </span><span class="vbscript"><% } %></span><br><span class="xml"> </span><br><span class="xml"> <span class="hljs-tag"><<span class="hljs-name">span</span>></span></span><br><span class="xml"> </span><span class="vbscript"><% <span class="hljs-keyword">if</span>(theme.ICP_license) {%></span><br><span class="xml"> <span class="hljs-tag"><<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"http://www.miitbeian.gov.cn/"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>></span></span><span class="vbscript"><%- theme.ICP_license %></span><span class="xml"><span class="hljs-tag"></<span class="hljs-name">a</span>></span><span class="hljs-tag"><<span class="hljs-name">br</span>></span></span><br><span class="xml"> </span><span class="vbscript"><% } %></span><br><span class="xml"> Power by <span class="hljs-tag"><<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"http://hexo.io/"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>></span>Hexo<span class="hljs-tag"></<span class="hljs-name">a</span>></span> Theme <span class="hljs-tag"><<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://github.com/yscoder/hexo-theme-indigo"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>></span>indigo<span class="hljs-tag"></<span class="hljs-name">a</span>></span></span><br><span class="xml"> <span class="hljs-tag"></<span class="hljs-name">span</span>></span></span><br><span class="xml"> <span class="hljs-tag"></<span class="hljs-name">p</span>></span></span><br><span class="xml"> <span class="hljs-tag"></<span class="hljs-name">div</span>></span></span><br><span class="xml"><span class="hljs-tag"></<span class="hljs-name">footer</span>></span></span><br></code></pre></td></tr></table></figure><h4 id="3、浏览器Console下出现node-waves插件等报错"><a href="#3、浏览器Console下出现node-waves插件等报错" class="headerlink" title="3、浏览器Console下出现node-waves插件等报错"></a>3、浏览器<code>Console</code>下出现<code>node-waves</code>插件等报错</h4><p>由于我不需要<code>node-waves</code>插件,所以我删除了加载插件的代码,设置配置项<code>cdn: false</code></p><ul><li><code>/themes/indigo/layout/_partial/script.ejs</code></li></ul><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment"><!--删除首行插件引入代码--></span><br><span class="hljs-comment"><!--<script src="//cdn.bootcss.com/node-waves/0.7.4/waves.min.js"></script>--></span><br></code></pre></td></tr></table></figure><ul><li><code>/themes/indigo/source/js/main.js</code></li><li><code>/themes/indigo/source/js/main.min.js</code></li></ul><figure class="highlight xml"><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><code class="hljs xml"><span class="hljs-comment"><!--修改报错为正常打印--></span><br><span class="hljs-comment"><!--console.error('Waves loading failed.')--></span><br>console.log('Waves loading failed.')<br></code></pre></td></tr></table></figure><h3 id="二、原功能迁移"><a href="#二、原功能迁移" class="headerlink" title="二、原功能迁移"></a>二、原功能迁移</h3><h4 id="1、图片功能"><a href="#1、图片功能" class="headerlink" title="1、图片功能"></a>1、图片功能</h4><p>在原主题中,我分析了添加图片的几种方案,参见:<a href="https://andergh.github.io/2018/07/31/%E5%A6%82%E4%BD%95%E5%9C%A8hexo%E5%8D%9A%E5%AE%A2%E4%B8%AD%E6%B7%BB%E5%8A%A0%E5%9B%BE%E7%89%87/">如何在hexo博客中添加图片</a>,想继续使用<code>hexo-asset-image</code>插件</p><p>但是由于<code>hexo 3</code>新版本的原因,<code>hexo-asset-image</code>插件出现了一些报错,查看<code>Issues</code>后决定本地修改插件代码</p><ol><li><code>io</code>路径问题,修改<code>MyBlog/node_modules/hexo-asset-image/index.js</code>文件</li></ol><figure class="highlight lasso"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs lasso"><span class="hljs-comment">// 第24行</span><br><span class="hljs-built_in">var</span> endPos = <span class="hljs-keyword">link</span>.length - <span class="hljs-number">1</span>; <br></code></pre></td></tr></table></figure><ol start="2"><li>执行<code>hexo</code>的命令时,会有<code>log</code>输出,修改<code>MyBlog/node_modules/hexo-asset-image/index.js</code>文件,注释第<code>60</code>行代码</li></ol><h4 id="2、音频功能"><a href="#2、音频功能" class="headerlink" title="2、音频功能"></a>2、音频功能</h4><p>以前的文档记录<a href="https://andergh.github.io/2018/08/01/%E5%A6%82%E4%BD%95%E5%9C%A8hexo%E5%8D%9A%E5%AE%A2%E6%B7%BB%E5%8A%A0%E9%9F%B3%E9%A2%91/">如何在hexo博客添加音频</a>。新主题中,依然准备采用<code>APlayer</code>播放器和<code>APlayer-Typecho</code>插件</p><blockquote><p>注意:由于<code>indigo</code>主题编译<code>js</code>路径的问题,所以<code>dist</code>文件夹放在<code>themes/indigo/source</code>路径下才行</p></blockquote><blockquote><p>本次同时更新<code>APlayer-Typecho</code>插件,为了能播放纯音乐,修改<code>Meting.min.js</code>中代码,添加一个歌词的字段,<code>data-lrcType</code>:是否打开歌词</p></blockquote><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ini"><span class="hljs-attr">g</span>=g.replace(<span class="hljs-string">':lrcType'</span>,d.dataset.lrcType)<br></code></pre></td></tr></table></figure><figure class="highlight routeros"><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><code class="hljs routeros"><link <span class="hljs-attribute">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attribute">href</span>=<span class="hljs-string">"/dist/APlayer.min.css"</span>><br><script <span class="hljs-attribute">src</span>=<span class="hljs-string">"/dist/APlayer.min.js"</span>></script><br><br><div <span class="hljs-attribute">class</span>=<span class="hljs-string">"aplayer"</span> <span class="hljs-attribute">data-id</span>=<span class="hljs-string">"496298744"</span> <span class="hljs-attribute">data-server</span>=<span class="hljs-string">"netease"</span> <span class="hljs-attribute">data-type</span>=<span class="hljs-string">"song"</span> <span class="hljs-attribute">data-lrcType</span>=<span class="hljs-literal">false</span>></div><br><br><div <span class="hljs-attribute">class</span>=<span class="hljs-string">"aplayer"</span> <span class="hljs-attribute">data-id</span>=<span class="hljs-string">"004VBMk71TdUuR"</span> <span class="hljs-attribute">data-server</span>=<span class="hljs-string">"tencent"</span> <span class="hljs-attribute">data-type</span>=<span class="hljs-string">"song"</span>></div><br><br><script <span class="hljs-attribute">src</span>=<span class="hljs-string">"/dist/Meting.min.js"</span>></script><br></code></pre></td></tr></table></figure><link rel="stylesheet" href="/dist/APlayer.min.css"><script src="/dist/APlayer.min.js"></script><div class="aplayer" data-id="496298744" data-server="netease" data-type="song" data-lrcType=false></div><div class="aplayer" data-id="004VBMk71TdUuR" data-server="tencent" data-type="song"></div><script src="/dist/Meting.min.js"></script><h4 id="3、视频功能"><a href="#3、视频功能" class="headerlink" title="3、视频功能"></a>3、视频功能</h4><p>暂不修改,<a href="https://andergh.github.io/2018/08/02/%E5%A6%82%E4%BD%95%E5%9C%A8hexo%E5%8D%9A%E5%AE%A2%E4%B8%AD%E6%B7%BB%E5%8A%A0%E8%A7%86%E9%A2%91/">如何在hexo博客中添加视频</a></p><h4 id="4、代码高亮"><a href="#4、代码高亮" class="headerlink" title="4、代码高亮"></a>4、代码高亮</h4><p>原文章地址:<a href="https://andergh.github.io/2019/04/01/%E4%BB%A3%E7%A0%81%E9%AB%98%E4%BA%AE/">https://andergh.github.io/2019/04/01/代码高亮/</a></p><ol><li>代码高亮</li></ol><ul><li>在<code>MyBlog/themes/indigo/layout/_partial/head.ejs</code>文件中第56行添加引用</li><li>对<code>/highlight/styles/xcode.css</code>修改,个性化部分样式</li></ul><figure class="highlight xml"><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><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/highlight/custom/xcode.css"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/highlight/highlight.pack.js"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span><br><span class="hljs-tag"><<span class="hljs-name">script</span>></span>hljs.initHighlightingOnLoad();<span class="hljs-tag"></<span class="hljs-name">script</span>></span><br></code></pre></td></tr></table></figure><ol start="2"><li>代码行号</li></ol><p>采用<code>Github</code>上第三方的插件<a href="https://github.com/wcoder/highlightjs-line-numbers.js"><code>highlightjs-line-numbers</code></a></p><ul><li>在<code>MyBlog/themes/indigo/layout/_partial/head.ejs</code>文件中第56行添加引用</li></ul><figure class="highlight xml"><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><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/highlight/custom/xcode.css"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/highlight/highlight.pack.js"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span><br><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/highlight/highlightjs-line-numbers/highlightjs-line-numbers.min.js"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span><br><span class="hljs-tag"><<span class="hljs-name">script</span>></span>hljs.initHighlightingOnLoad();<span class="hljs-tag"></<span class="hljs-name">script</span>></span><br><span class="hljs-tag"><<span class="hljs-name">script</span>></span>hljs.initLineNumbersOnLoad();<span class="hljs-tag"></<span class="hljs-name">script</span>></span><br></code></pre></td></tr></table></figure><ol start="3"><li>修改行号样式</li></ol><ul><li>由于<code>highlightjs-line-numbers</code>插件当代码只有一行时不会显示行号,所以需要修改源码</li></ul><figure class="highlight awk"><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><code class="hljs awk"><span class="hljs-regexp">//</span> change by guanhao at <span class="hljs-number">20200227</span> 修改判断逻辑,大于改成大于等于,单行代码也添加行号<br><span class="hljs-regexp">//</span> <span class="hljs-keyword">if</span> (lines.length > firstLineIndex) {<br><span class="hljs-keyword">if</span> (lines.length >= firstLineIndex) {<br></code></pre></td></tr></table></figure><ul><li>自定义其他css样式</li></ul><p>找到<code>MyBlog/themes/indigo/source/css/style.less</code>文件,添加自定义的样式文件,并创建相应的样式文件</p><figure class="highlight css"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><code class="hljs css"><span class="hljs-comment">/* 个性化样式 */</span><br><br>pre {<br> <span class="hljs-attribute">padding</span>: <span class="hljs-number">0px</span> <span class="hljs-meta">!important</span>;<br> <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">10px</span> <span class="hljs-meta">!important</span>;<br> <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">10px</span> <span class="hljs-meta">!important</span>;<br>}<br><br><span class="hljs-selector-tag">code</span> {<br> <span class="hljs-attribute">color</span>: <span class="hljs-number">#4d4d4c</span> <span class="hljs-meta">!important</span>;<br> <span class="hljs-attribute">margin-right</span>: <span class="hljs-number">0px</span> <span class="hljs-meta">!important</span>;<br> <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">0px</span> <span class="hljs-meta">!important</span>;<br> <span class="hljs-attribute">padding-left</span>: <span class="hljs-number">0px</span> <span class="hljs-meta">!important</span>;<br> <span class="hljs-attribute">padding-right</span>: <span class="hljs-number">0px</span> <span class="hljs-meta">!important</span>;<br>}<br><br><span class="hljs-selector-tag">a</span> <span class="hljs-selector-tag">code</span> {<br> <span class="hljs-attribute">color</span>: <span class="hljs-number">#ff4081</span> <span class="hljs-meta">!important</span>;<br>}<br><br><span class="hljs-selector-class">.hljs-ln</span> {<br> <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">0px</span> <span class="hljs-meta">!important</span>;<br> <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#dedede</span> <span class="hljs-meta">!important</span>;<br>}<br><br><span class="hljs-selector-class">.hljs-ln</span> <span class="hljs-selector-tag">tr</span> {<br> <span class="hljs-attribute">height</span>: <span class="hljs-number">26px</span> <span class="hljs-meta">!important</span>;<br>}<br><br><span class="hljs-selector-class">.hljs-ln-numbers</span> {<br> <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> <span class="hljs-meta">!important</span>;<br> <span class="hljs-attribute">border-right</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#dedede</span> <span class="hljs-meta">!important</span>;<br> <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#eaeaea</span> <span class="hljs-meta">!important</span>;<br> <span class="hljs-attribute">height</span>: <span class="hljs-number">26px</span> <span class="hljs-meta">!important</span>;<br> <span class="hljs-attribute">width</span>: <span class="hljs-number">27px</span> <span class="hljs-meta">!important</span>;<br> <span class="hljs-attribute">padding-left</span>: <span class="hljs-number">5px</span> <span class="hljs-meta">!important</span>;<br> <span class="hljs-attribute">padding-right</span>: <span class="hljs-number">5px</span> <span class="hljs-meta">!important</span>;<br>}<br><br><span class="hljs-selector-class">.hljs-ln-code</span> {<br> <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> <span class="hljs-meta">!important</span>;<br> <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#fbfbfb</span> <span class="hljs-meta">!important</span>;<br> <span class="hljs-attribute">height</span>: <span class="hljs-number">26px</span> <span class="hljs-meta">!important</span>;<br>}<br><br><span class="hljs-selector-class">.hljs-ln-n</span> {<br> <span class="hljs-attribute">text-align</span>: center <span class="hljs-meta">!important</span>;<br>}<br></code></pre></td></tr></table></figure><h3 id="三、上传部署"><a href="#三、上传部署" class="headerlink" title="三、上传部署"></a>三、上传部署</h3><p>最新版本<code>hexo</code>部署包中缺少<code>hexo-deployer-git</code>插件,导致部署到<code>git</code>时出现报错:<code>ERROR Deployer not found: git</code>,需要安装<code>hexo-deployer-git</code>插件才行</p><figure class="highlight ada"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ada">$ npm install hexo-deployer-git <span class="hljs-comment">--save</span><br></code></pre></td></tr></table></figure>]]></content>
<categories>
<category>Hexo</category>
</categories>
<tags>
<tag>Hexo</tag>
</tags>
</entry>
<entry>
<title>探究KVO底层实现</title>
<link href="/2019/12/06/%E6%8E%A2%E7%A9%B6KVO%E5%BA%95%E5%B1%82%E5%AE%9E%E7%8E%B0/"/>
<url>/2019/12/06/%E6%8E%A2%E7%A9%B6KVO%E5%BA%95%E5%B1%82%E5%AE%9E%E7%8E%B0/</url>
<content type="html"><![CDATA[<p>本文参考<a href="https://www.jianshu.com/p/0aa83ac521ba">《iOS窥探KVO底层实现原理篇》</a></p><h4 id="一、定义"><a href="#一、定义" class="headerlink" title="一、定义"></a>一、定义</h4><blockquote><p><code>KVO</code>全称为<code>Key Value Observing</code>,键值观察机制,由<code>NSKeyValueObserving</code>协议提供支持,<code>NSObject</code>类继承了该协议,所以<code>NSObject</code>的子类都可使用该方法</p></blockquote><h4 id="二、方法"><a href="#二、方法" class="headerlink" title="二、方法"></a>二、方法</h4><figure class="highlight less"><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><code class="hljs less"><span class="hljs-comment">/* Register or deregister as an observer of the value at a key path relative to the receiver. The options determine what is included in observer notifications and when they're sent, as described above, and the context is passed in observer notifications as described above. You should use -removeObserver:forKeyPath:context: instead of -removeObserver:forKeyPath: whenever possible because it allows you to more precisely specify your intent. When the same observer is registered for the same key path multiple times, but with different context pointers each time, -removeObserver:forKeyPath: has to guess at the context pointer when deciding what exactly to remove, and it can guess wrong.</span><br><span class="hljs-comment">在相对于接收者的关键路径上注册或注销该值的观察者。 这些选项确定观察者通知中包括的内容以及何时发送它们,如上所述,并且上下文如上所述在观察者通知中传递上下文。 您应尽可能使用removeObserver:forKeyPath:context:而不是removeObserver:forKeyPath:,因为它可以让您更精确地指定意图。 当同一观察者多次注册相同的KeyPath路径,但每次都使用不同的上下文指针时,removeObserver:forKeyPath:在确定要删除的对象时必须猜测上下文指针,并且可能会猜错。</span><br><span class="hljs-comment">*/</span><br><span class="hljs-selector-tag">-</span> (void)<span class="hljs-selector-tag">addObserver</span>:(NSObject *)<span class="hljs-selector-tag">observer</span> <span class="hljs-selector-tag">forKeyPath</span>:(NSString *)<span class="hljs-selector-tag">keyPath</span> <span class="hljs-selector-tag">options</span>:(NSKeyValueObservingOptions)<span class="hljs-selector-tag">options</span> <span class="hljs-selector-tag">context</span>:(nullable void *)<span class="hljs-selector-tag">context</span>;<br><span class="hljs-selector-tag">-</span> (void)<span class="hljs-selector-tag">removeObserver</span>:(NSObject *)<span class="hljs-selector-tag">observer</span> <span class="hljs-selector-tag">forKeyPath</span>:(NSString *)<span class="hljs-selector-tag">keyPath</span> <span class="hljs-selector-tag">context</span>:(nullable void *)<span class="hljs-selector-tag">context</span> <span class="hljs-selector-tag">API_AVAILABLE</span>(macos(<span class="hljs-number">10.7</span>), ios(<span class="hljs-number">5.0</span>), watchos(<span class="hljs-number">2.0</span>), tvos(<span class="hljs-number">9.0</span>));<br><span class="hljs-selector-tag">-</span> (void)<span class="hljs-selector-tag">removeObserver</span>:(NSObject *)<span class="hljs-selector-tag">observer</span> <span class="hljs-selector-tag">forKeyPath</span>:(NSString *)<span class="hljs-selector-tag">keyPath</span>;<br></code></pre></td></tr></table></figure><figure class="highlight objectivec"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs objectivec"><span class="hljs-comment">/* Options for use with -addObserver:forKeyPath:options:context: and -addObserver:toObjectsAtIndexes:forKeyPath:options:context:.</span><br><span class="hljs-comment">*/</span><br><span class="hljs-keyword">typedef</span> <span class="hljs-built_in">NS_OPTIONS</span>(<span class="hljs-built_in">NSUInteger</span>, <span class="hljs-built_in">NSKeyValueObservingOptions</span>) {<br><br> <span class="hljs-comment">/* Whether the change dictionaries sent in notifications should contain NSKeyValueChangeNewKey and NSKeyValueChangeOldKey entries, respectively.</span><br><span class="hljs-comment"> */</span><br> <span class="hljs-built_in">NSKeyValueObservingOptionNew</span> = <span class="hljs-number">0x01</span>,<br> <span class="hljs-built_in">NSKeyValueObservingOptionOld</span> = <span class="hljs-number">0x02</span>,<br><br> <span class="hljs-comment">/* Whether a notification should be sent to the observer immediately, before the observer registration method even returns. The change dictionary in the notification will always contain an NSKeyValueChangeNewKey entry if NSKeyValueObservingOptionNew is also specified but will never contain an NSKeyValueChangeOldKey entry. (In an initial notification the current value of the observed property may be old, but it's new to the observer.) You can use this option instead of explicitly invoking, at the same time, code that is also invoked by the observer's -observeValueForKeyPath:ofObject:change:context: method. When this option is used with -addObserver:toObjectsAtIndexes:forKeyPath:options:context: a notification will be sent for each indexed object to which the observer is being added.</span><br><span class="hljs-comment"> 在观察者注册方法返回之前是否立即将通知发送给观察者。 如果还指定了NSKeyValueObservingOptionNew,则通知中的更改字典将始终包含NSKeyValueChangeNewKey条目,但绝不包含NSKeyValueChangeOldKey条目。 (在初始通知中,observed属性的当前值可能是旧的,但对于观察者来说是新的。)您可以使用此选项,而不是同时显式调用观察者的observeValueForKeyPath:ofObject:change:context:方法。 与addObserver:toObjectsAtIndexes:forKeyPath:options:context一起使用此选项时,将向要添加观察者的每个索引对象发送通知。</span><br><span class="hljs-comment"> */</span><br> <span class="hljs-built_in">NSKeyValueObservingOptionInitial</span> API_AVAILABLE(macos(<span class="hljs-number">10.5</span>), ios(<span class="hljs-number">2.0</span>), watchos(<span class="hljs-number">2.0</span>), tvos(<span class="hljs-number">9.0</span>)) = <span class="hljs-number">0x04</span>,<br><br> <span class="hljs-comment">/* Whether separate notifications should be sent to the observer before and after each change, instead of a single notification after the change. The change dictionary in a notification sent before a change always contains an NSKeyValueChangeNotificationIsPriorKey entry whose value is [NSNumber numberWithBool:YES], but never contains an NSKeyValueChangeNewKey entry. You can use this option when the observer's own KVO-compliance requires it to invoke one of the -willChange... methods for one of its own properties, and the value of that property depends on the value of the observed object's property. (In that situation it's too late to easily invoke -willChange... properly in response to receiving an -observeValueForKeyPath:ofObject:change:context: message after the change.)</span><br><span class="hljs-comment"></span><br><span class="hljs-comment">When this option is specified, the change dictionary in a notification sent after a change contains the same entries that it would contain if this option were not specified, except for ordered unique to-many relationships represented by NSOrderedSets. For those, for NSKeyValueChangeInsertion and NSKeyValueChangeReplacement changes, the change dictionary for a will-change notification contains an NSKeyValueChangeIndexesKey (and NSKeyValueChangeOldKey in the case of Replacement where the NSKeyValueObservingOptionOld option was specified at registration time) which give the indexes (and objects) which *may* be changed by the operation. The second notification, after the change, contains entries reporting what did actually change. For NSKeyValueChangeRemoval changes, removals by index are precise.</span><br><span class="hljs-comment"> 是否应在每次更改之前和之后将单独的通知发送给观察者,而不是在更改之后将单个通知发送给观察者。更改之前发送的通知中的更改字典始终包含NSKeyValueChangeNotificationIsPriorKey条目,其值为[NSNumber numberWithBool:YES],但从不包含NSKeyValueChangeNewKey条目。当观察者自己的KVO兼容性要求它为其自身的属性之一调用willChange ...方法之一时,可以使用此选项,并且该属性的值取决于所观察对象的属性的值。 (在那种情况下,为响应更改后收到的observeValueForKeyPath:ofObject:change:context:消息,正确地轻松调用willChange ...为时已晚。)</span><br><span class="hljs-comment"></span><br><span class="hljs-comment">指定此选项后,更改后发送的通知中的更改字典包含与未指定此选项时将包含的条目相同的条目,但NSOrderedSets表示的有序唯一对多关系除外。对于这些更改,对于NSKeyValueChangeInsertion和NSKeyValueChangeReplacement更改,遗嘱变更通知的更改字典包含NSKeyValueChangeIndexesKey(在替换的情况下为NSKeyValueChangeChangeOldKey,在注册时指定了NSKeyValueObservingOptionOld选项的情况下),其索引(和对象)可以* *通过操作更改。更改后的第二个通知包含报告实际更改内容的条目。对于NSKeyValueChangeRemoval更改,按索引的删除是精确的。</span><br><span class="hljs-comment"> */</span><br> <span class="hljs-built_in">NSKeyValueObservingOptionPrior</span> API_AVAILABLE(macos(<span class="hljs-number">10.5</span>), ios(<span class="hljs-number">2.0</span>), watchos(<span class="hljs-number">2.0</span>), tvos(<span class="hljs-number">9.0</span>)) = <span class="hljs-number">0x08</span><br><br>};<br></code></pre></td></tr></table></figure><figure class="highlight objectivec"><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><code class="hljs objectivec"><span class="hljs-keyword">typedef</span> <span class="hljs-built_in">NSString</span> * <span class="hljs-built_in">NSKeyValueChangeKey</span> <span class="hljs-built_in">NS_STRING_ENUM</span>;<br><span class="hljs-comment">/* Keys for entries in change dictionaries. See the comments for -observeValueForKeyPath:ofObject:change:context: for more information.</span><br><span class="hljs-comment">*/</span><br>FOUNDATION_EXPORT <span class="hljs-built_in">NSKeyValueChangeKey</span> <span class="hljs-keyword">const</span> <span class="hljs-built_in">NSKeyValueChangeKindKey</span>;<br>FOUNDATION_EXPORT <span class="hljs-built_in">NSKeyValueChangeKey</span> <span class="hljs-keyword">const</span> <span class="hljs-built_in">NSKeyValueChangeNewKey</span>;<br>FOUNDATION_EXPORT <span class="hljs-built_in">NSKeyValueChangeKey</span> <span class="hljs-keyword">const</span> <span class="hljs-built_in">NSKeyValueChangeOldKey</span>;<br>FOUNDATION_EXPORT <span class="hljs-built_in">NSKeyValueChangeKey</span> <span class="hljs-keyword">const</span> <span class="hljs-built_in">NSKeyValueChangeIndexesKey</span>;<br>FOUNDATION_EXPORT <span class="hljs-built_in">NSKeyValueChangeKey</span> <span class="hljs-keyword">const</span> <span class="hljs-built_in">NSKeyValueChangeNotificationIsPriorKey</span> API_AVAILABLE(macos(<span class="hljs-number">10.5</span>), ios(<span class="hljs-number">2.0</span>), watchos(<span class="hljs-number">2.0</span>), tvos(<span class="hljs-number">9.0</span>));<br></code></pre></td></tr></table></figure><h4 id="三、代码测试"><a href="#三、代码测试" class="headerlink" title="三、代码测试"></a>三、代码测试</h4><figure class="highlight reasonml"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><code class="hljs reasonml">#import <span class="hljs-string">"ViewController.h"</span><br>#import <span class="hljs-string">"AObject.h"</span><br>#import <objc/runtime.h><br><br>@implementation ViewController<br><br>- (void)viewDidLoad {<br> <span class="hljs-literal">[<span class="hljs-identifier">super</span> <span class="hljs-identifier">viewDidLoad</span>]</span>;<br> <span class="hljs-comment">// Do any additional setup after loading the view.</span><br> <br> AObject *a1 = <span class="hljs-literal">[[AO<span class="hljs-identifier">bject</span> <span class="hljs-identifier">alloc</span>]</span> init];<br> AObject *a2 = <span class="hljs-literal">[[AO<span class="hljs-identifier">bject</span> <span class="hljs-identifier">alloc</span>]</span> init];<br> <br> <span class="hljs-constructor">NSLog(@<span class="hljs-string">"内存:%p,%p"</span>, <span class="hljs-params">a1</span>, <span class="hljs-params">a2</span>)</span>;<br> <span class="hljs-constructor">NSLog(@<span class="hljs-string">"类:%@,%@"</span>, <span class="hljs-params">a1</span>.<span class="hljs-params">class</span>, <span class="hljs-params">a2</span>.<span class="hljs-params">class</span>)</span>;<br> <span class="hljs-constructor">NSLog(@<span class="hljs-string">"isa:%@ %@"</span>, <span class="hljs-params">object_getClass</span>(<span class="hljs-params">a1</span>)</span>, <span class="hljs-keyword">object</span><span class="hljs-constructor">_getClass(<span class="hljs-params">a2</span>)</span>);<br> <br> SEL sel = @selector(setP:);<br> IMP imp1 = <span class="hljs-literal">[<span class="hljs-identifier">a1</span> <span class="hljs-identifier">methodForSelector</span>:<span class="hljs-identifier">sel</span>]</span>;<br> IMP imp2 = <span class="hljs-literal">[<span class="hljs-identifier">a2</span> <span class="hljs-identifier">methodForSelector</span>:<span class="hljs-identifier">sel</span>]</span>;<br> <span class="hljs-constructor">NSLog(@<span class="hljs-string">"IMP指针:%p %p"</span>, <span class="hljs-params">imp1</span>, <span class="hljs-params">imp2</span>)</span>;<br> <br> <span class="hljs-literal">[<span class="hljs-identifier">a1</span> <span class="hljs-identifier">addObserver</span>:<span class="hljs-identifier">self</span> <span class="hljs-identifier">forKeyPath</span>:@"<span class="hljs-identifier">p</span>" <span class="hljs-identifier">options</span>:(NSK<span class="hljs-identifier">eyValueObservingOptionNew</span>) <span class="hljs-identifier">context</span>:<span class="hljs-identifier">nil</span>]</span>;<br> <br> <span class="hljs-constructor">NSLog(@<span class="hljs-string">"添加KVO后内存:%p,%p"</span>, <span class="hljs-params">a1</span>, <span class="hljs-params">a2</span>)</span>;<br> <span class="hljs-constructor">NSLog(@<span class="hljs-string">"添加KVO后类:%@,%@"</span>, <span class="hljs-params">a1</span>.<span class="hljs-params">class</span>, <span class="hljs-params">a2</span>.<span class="hljs-params">class</span>)</span>;<br> <span class="hljs-constructor">NSLog(@<span class="hljs-string">"添加KVO后isa:%@ %@"</span>, <span class="hljs-params">object_getClass</span>(<span class="hljs-params">a1</span>)</span>, <span class="hljs-keyword">object</span><span class="hljs-constructor">_getClass(<span class="hljs-params">a2</span>)</span>);<br> <br> imp1 = <span class="hljs-literal">[<span class="hljs-identifier">a1</span> <span class="hljs-identifier">methodForSelector</span>:<span class="hljs-identifier">sel</span>]</span>;<br> imp2 = <span class="hljs-literal">[<span class="hljs-identifier">a2</span> <span class="hljs-identifier">methodForSelector</span>:<span class="hljs-identifier">sel</span>]</span>;<br> <span class="hljs-constructor">NSLog(@<span class="hljs-string">"添加KVO后IMP指针:%p %p"</span>, <span class="hljs-params">imp1</span>, <span class="hljs-params">imp2</span>)</span>;<br> <br> a1.p = @<span class="hljs-string">"1"</span>;<br> a2.p = @<span class="hljs-string">"2"</span>;<br>}<br><br>- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)<span class="hljs-keyword">object</span> change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {<br> <span class="hljs-constructor">NSLog(@<span class="hljs-string">"%@"</span>, <span class="hljs-params">change</span>)</span>;<br>}<br><br>@<span class="hljs-keyword">end</span><br><br><span class="hljs-number">2019</span>-<span class="hljs-number">12</span>-<span class="hljs-number">06</span> <span class="hljs-number">13</span>:<span class="hljs-number">56</span>:<span class="hljs-number">30.457732</span>+<span class="hljs-number">0800</span> testKVO<span class="hljs-literal">[<span class="hljs-number">854</span>:<span class="hljs-number">62432</span>]</span> 内存:<span class="hljs-number">0x283a0cc70</span>,<span class="hljs-number">0x283a0cc90</span><br><span class="hljs-number">2019</span>-<span class="hljs-number">12</span>-<span class="hljs-number">06</span> <span class="hljs-number">13</span>:<span class="hljs-number">56</span>:<span class="hljs-number">30.457797</span>+<span class="hljs-number">0800</span> testKVO<span class="hljs-literal">[<span class="hljs-number">854</span>:<span class="hljs-number">62432</span>]</span> 类:AObject,AObject<br><span class="hljs-number">2019</span>-<span class="hljs-number">12</span>-<span class="hljs-number">06</span> <span class="hljs-number">13</span>:<span class="hljs-number">56</span>:<span class="hljs-number">30.457821</span>+<span class="hljs-number">0800</span> testKVO<span class="hljs-literal">[<span class="hljs-number">854</span>:<span class="hljs-number">62432</span>]</span> isa:AObject AObject<br><span class="hljs-number">2019</span>-<span class="hljs-number">12</span>-<span class="hljs-number">06</span> <span class="hljs-number">13</span>:<span class="hljs-number">56</span>:<span class="hljs-number">30.457839</span>+<span class="hljs-number">0800</span> testKVO<span class="hljs-literal">[<span class="hljs-number">854</span>:<span class="hljs-number">62432</span>]</span> IMP指针:<span class="hljs-number">0x1009e6150</span> <span class="hljs-number">0x1009e6150</span><br><span class="hljs-number">2019</span>-<span class="hljs-number">12</span>-<span class="hljs-number">06</span> <span class="hljs-number">13</span>:<span class="hljs-number">56</span>:<span class="hljs-number">30.458057</span>+<span class="hljs-number">0800</span> testKVO<span class="hljs-literal">[<span class="hljs-number">854</span>:<span class="hljs-number">62432</span>]</span> 添加KVO后内存:<span class="hljs-number">0x283a0cc70</span>,<span class="hljs-number">0x283a0cc90</span><br><span class="hljs-number">2019</span>-<span class="hljs-number">12</span>-<span class="hljs-number">06</span> <span class="hljs-number">13</span>:<span class="hljs-number">56</span>:<span class="hljs-number">30.458084</span>+<span class="hljs-number">0800</span> testKVO<span class="hljs-literal">[<span class="hljs-number">854</span>:<span class="hljs-number">62432</span>]</span> 添加KVO后类:AObject,AObject<br><span class="hljs-number">2019</span>-<span class="hljs-number">12</span>-<span class="hljs-number">06</span> <span class="hljs-number">13</span>:<span class="hljs-number">56</span>:<span class="hljs-number">30.458106</span>+<span class="hljs-number">0800</span> testKVO<span class="hljs-literal">[<span class="hljs-number">854</span>:<span class="hljs-number">62432</span>]</span> 添加KVO后isa:NSKVONotifying_AObject AObject<br><span class="hljs-number">2019</span>-<span class="hljs-number">12</span>-<span class="hljs-number">06</span> <span class="hljs-number">13</span>:<span class="hljs-number">56</span>:<span class="hljs-number">30.458124</span>+<span class="hljs-number">0800</span> testKVO<span class="hljs-literal">[<span class="hljs-number">854</span>:<span class="hljs-number">62432</span>]</span> 添加KVO后IMP指针:<span class="hljs-number">0x1842b9020</span> <span class="hljs-number">0x1009e6150</span><br></code></pre></td></tr></table></figure><ul><li>添加了<code>KVO</code>之后<code>a1</code>修改<code>p</code>值之后 不再调用<code>AObject</code>的<code>setP:</code>方法 ,而 <code>a2</code>没有添加监听,依然正常调用<code>setP:</code>方法,由此可以得出系统修改了默认方法实现</li></ul><figure class="highlight apache"><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><code class="hljs apache"> <span class="hljs-attribute">NSLog</span>(@<span class="hljs-string">"添加KVO后isa:%@ %@"</span>, object_getClass(a<span class="hljs-number">1</span>), object_getClass(a<span class="hljs-number">2</span>));<br> <span class="hljs-attribute">NSLog</span>(@<span class="hljs-string">"添加KVO后superclass:%@ %@"</span>, class_getSuperclass(object_getClass(a<span class="hljs-number">1</span>)), class_getSuperclass(object_getClass(a<span class="hljs-number">2</span>)));<br> <br><span class="hljs-attribute">2019</span>-<span class="hljs-number">12</span>-<span class="hljs-number">06</span> <span class="hljs-number">14</span>:<span class="hljs-number">04</span>:<span class="hljs-number">00</span>.<span class="hljs-number">196164</span>+<span class="hljs-number">0800</span> testKVO[<span class="hljs-number">881</span>:<span class="hljs-number">64017</span>] 添加KVO后isa:NSKVONotifying_AObject AObject<br><span class="hljs-attribute">2019</span>-<span class="hljs-number">12</span>-<span class="hljs-number">06</span> <span class="hljs-number">14</span>:<span class="hljs-number">04</span>:<span class="hljs-number">00</span>.<span class="hljs-number">196194</span>+<span class="hljs-number">0800</span> testKVO[<span class="hljs-number">881</span>:<span class="hljs-number">64017</span>] 添加KVO后superclass:AObject NSObject<br></code></pre></td></tr></table></figure><ul><li><code>NSKVONotifying_AObjectn</code>是苹果动态创建的<code>AObject</code>子类</li></ul><figure class="highlight apache"><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><code class="hljs apache"> <span class="hljs-attribute">NSString</span> *methods<span class="hljs-number">1</span> =<span class="hljs-meta"> [self printMethods:object_getClass(a1)];</span><br><span class="hljs-meta"> NSString *methods2 = [self printMethods:object_getClass(a2)];</span><br><span class="hljs-meta"> NSLog(@"%@", methods1);</span><br><span class="hljs-meta"> NSLog(@"%@", methods2);</span><br><span class="hljs-meta"> </span><br><span class="hljs-meta">2019-12-06 14:08:10.447603+0800 testKVO[908:65143] [</span><br><span class="hljs-meta">setP:</span><br><span class="hljs-meta">class</span><br><span class="hljs-meta">dealloc</span><br><span class="hljs-meta">_isKVOA</span><br><span class="hljs-meta">]</span><br><span class="hljs-attribute">2019</span>-<span class="hljs-number">12</span>-<span class="hljs-number">06</span> <span class="hljs-number">14</span>:<span class="hljs-number">08</span>:<span class="hljs-number">10</span>.<span class="hljs-number">447618</span>+<span class="hljs-number">0800</span> testKVO[<span class="hljs-number">908</span>:<span class="hljs-number">65143</span>]<span class="hljs-meta"> [</span><br><span class="hljs-meta">.cxx_destruct</span><br><span class="hljs-meta">p</span><br><span class="hljs-meta">setP:</span><br><span class="hljs-meta">]</span><br></code></pre></td></tr></table></figure><p>从输出结果可以看出来<code>NSKVONotifying_AObject</code>内部也有一个<code>setP:</code>方法 还重写了<code>class</code>和<code>dealloc</code>方法,由此,给出如下猜想:</p><ul><li>添加<code>KVO</code>之后,动态创建了一个子类,继承所观察的类,命名<code>NSKVONotifying_*</code>,重写了所观察属性的<code>set</code>方法,并且通过重写<code>class</code>方法隐藏了子类的存在,在<code>dealloc</code>中进行了释放等操作</li><li>属性值发生变化时,触发了<code>NSKVONotifying_*</code>重写的<code>set</code>方法,此时便可以得到原值和新值,并在赋值时触发给定的相应方法</li><li>这就能解释:如果观察的属性不存在<code>set</code>方法(直接创建的实例),那么<code>KVO</code>观察就不会生效</li></ul>]]></content>
<categories>
<category>iOS</category>
</categories>
<tags>
<tag>iOS</tag>
<tag>KVO</tag>
</tags>
</entry>
<entry>
<title>iOS崩溃排查</title>
<link href="/2019/12/05/iOS%E5%B4%A9%E6%BA%83%E6%8E%92%E6%9F%A5/"/>
<url>/2019/12/05/iOS%E5%B4%A9%E6%BA%83%E6%8E%92%E6%9F%A5/</url>
<content type="html"><![CDATA[<h3 id="一、记录崩溃日志"><a href="#一、记录崩溃日志" class="headerlink" title="一、记录崩溃日志"></a>一、记录崩溃日志</h3><h4 id="1、连接设备,直接通过Xcode获取"><a href="#1、连接设备,直接通过Xcode获取" class="headerlink" title="1、连接设备,直接通过Xcode获取"></a>1、连接设备,直接通过<code>Xcode</code>获取</h4><blockquote><p>在菜单栏找到<code>Devices and Simulators</code>,找到<code>View Device Logs</code>,根据日期包名等信息即可以找到对应的闪退日志,稍等一段时间后,<code>Xcode</code>会自动将日志符号化,此处日志导出后,会生成对应的<code>.crash</code>格式的崩溃日志</p></blockquote><h4 id="2、设备中提取"><a href="#2、设备中提取" class="headerlink" title="2、设备中提取"></a>2、设备中提取</h4><blockquote><p><code>iPhone</code>设置里面,依次找到隐私-分析-分析数据,此处会记录设备上所有的日志,同样找到相应的日志,点击后可以复制出来,但此处日志没有经过符号化,还需要再进行符号化才能看懂</p></blockquote><h4 id="3、代码中系统方法记录"><a href="#3、代码中系统方法记录" class="headerlink" title="3、代码中系统方法记录"></a>3、代码中系统方法记录</h4><figure class="highlight objectivec"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs objectivec">FOUNDATION_EXPORT <span class="hljs-keyword">void</span> <span class="hljs-built_in">NSSetUncaughtExceptionHandler</span>(<span class="hljs-built_in">NSUncaughtExceptionHandler</span> * _Nullable);<br></code></pre></td></tr></table></figure><blockquote><p>在代码中使用系统提供的<code>API</code>记录日志后,再通过网络上传,这样就能统计到所有设备上的崩溃日志了</p></blockquote><h4 id="4、第三方库KSCrash"><a href="#4、第三方库KSCrash" class="headerlink" title="4、第三方库KSCrash"></a>4、第三方库<a href="https://github.com/kstenerud/KSCrash"><code>KSCrash</code></a></h4><p>相比系统方法,有些第三方库的日志记录更为精确,例如<a href="https://github.com/kstenerud/KSCrash"><code>KSCrash</code></a></p><h3 id="二、-crash符号化"><a href="#二、-crash符号化" class="headerlink" title="二、.crash符号化"></a>二、<code>.crash</code>符号化</h3><h4 id="1、dSYM符号文件"><a href="#1、dSYM符号文件" class="headerlink" title="1、dSYM符号文件"></a>1、<code>dSYM</code>符号文件</h4><blockquote><p><code>dSYM</code>文件是指具有调试信息的目标文件,每次打包时<code>Xcode</code>菜单栏中<code>Organizer</code>下回生成<code>Archives</code>记录,右键<code>Show in Finder</code>可以找到对应的<code>.xcarchive</code>文件,在该文件包内容中可以找到<code>dSYMs</code>文件夹,里面包含<code>dSYM</code>文件,如果没有,需要检查<code>Xcode</code>相关的打包配置参数</p></blockquote><h4 id="2、-找到Xcode的symbolicatecrash脚本"><a href="#2、-找到Xcode的symbolicatecrash脚本" class="headerlink" title="2、 找到Xcode的symbolicatecrash脚本"></a>2、 找到<code>Xcode</code>的<code>symbolicatecrash</code>脚本</h4><p>在终端中输入命令</p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs gradle">$ <span class="hljs-keyword">find</span> <span class="hljs-regexp">/Applications/</span>Xcode.app -name symbolicatecrash -type f<br></code></pre></td></tr></table></figure><p>其中<code>Xcode.app</code>的路径请以本机路径为准,一段时间后,即可以找到几个<code>symbolicatecrash</code>脚本,拷贝其中一个脚本即可</p><h4 id="3、校验uuid"><a href="#3、校验uuid" class="headerlink" title="3、校验uuid"></a>3、校验<code>uuid</code></h4><p>查看<code>dSYM</code>文件的<code>uuid</code></p><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">$ xcrun dwarfdump --uuid xx<span class="hljs-regexp">/xx/</span>.dSYM<br></code></pre></td></tr></table></figure><p>查看<code>app</code>的<code>uuid</code></p><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">$ xcrun dwarfdump --uuid xx<span class="hljs-regexp">/xx/</span>.app<br></code></pre></td></tr></table></figure><p>查看<code>crash</code>文件的<code>uuid</code>,在<code>crash</code>文件中找到<code>Binary Images</code>,其下面的第一行类似于下面代码,尖括号中的就是<code>uuid</code></p><figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">0x1021d4000</span> - <span class="hljs-number">0</span>x<span class="hljs-number">103</span>d<span class="hljs-number">97</span>fff +name arm<span class="hljs-number">64</span> <<span class="hljs-number">574</span>a<span class="hljs-number">9</span>bf<span class="hljs-number">6</span>c<span class="hljs-number">9133</span>dd<span class="hljs-number">28</span>f<span class="hljs-number">0238271676</span>b<span class="hljs-number">1</span>aa> /private/var/containers/Bundle/Application/F<span class="hljs-number">2986301</span>-<span class="hljs-number">7085</span>-<span class="hljs-number">4018</span>-A<span class="hljs-number">6</span>DD-<span class="hljs-number">64</span>AB<span class="hljs-number">69</span>F<span class="hljs-number">95</span>AA<span class="hljs-number">2</span>/name.app/name<br></code></pre></td></tr></table></figure><h4 id="4、符号化"><a href="#4、符号化" class="headerlink" title="4、符号化"></a>4、符号化</h4><p>将<code>symbolicatecrash</code>脚本、<code>dSYM</code>文件、<code>.app</code>、<code>.crash</code>文件放在一起,要先确保三个文件为同一个<code>app</code>打包产生的,使用如下命令行即可符号化</p><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">$ xx<span class="hljs-regexp">/xx/</span>symbolicatecrash xx<span class="hljs-regexp">/xx/</span>.crash xx<span class="hljs-regexp">/xx/</span>.dSYM > xx<span class="hljs-regexp">/xx/</span>.log<br></code></pre></td></tr></table></figure><p>如果出现报错,则需要重置下环境变量</p><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">$ export DEVELOPER_DIR=<span class="hljs-regexp">/Applications/</span>Xcode.app<span class="hljs-regexp">/Contents/</span>Developer<br></code></pre></td></tr></table></figure><h3 id="三、dSYMTools"><a href="#三、dSYMTools" class="headerlink" title="三、dSYMTools"></a>三、<a href="https://github.com/answer-huang/dSYMTools"><code>dSYMTools</code></a></h3><p><code>github</code>有做成<code>mac app</code>的工程,可以直接使用</p>]]></content>
<categories>
<category>iOS</category>
</categories>
<tags>
<tag>iOS</tag>
<tag>崩溃排查</tag>
</tags>
</entry>
<entry>
<title>iOS关于RSA的一些基础知识</title>
<link href="/2019/11/04/iOS%E5%85%B3%E4%BA%8ERSA%E7%9A%84%E4%B8%80%E4%BA%9B%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/"/>
<url>/2019/11/04/iOS%E5%85%B3%E4%BA%8ERSA%E7%9A%84%E4%B8%80%E4%BA%9B%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/</url>
<content type="html"><![CDATA[<h4 id="一、基础概念"><a href="#一、基础概念" class="headerlink" title="一、基础概念"></a>一、基础概念</h4><ul><li><p><code>RSA</code>加密算法是最常用的非对称加密算法,目前普遍认为是最优秀的方案之一,关于<code>RSA</code>的数学原理和方法,这里不做说明,感兴趣的可以自行了解下。本文主要介绍<code>RSA</code>的一些常用的基础知识</p></li><li><p><code>RSA</code>分为公钥和私钥,生成时会需要传入参数,秘钥位数和秘钥格式,秘钥位数有<code>512bit</code>、<code>1024bit</code>、<code>2048bit</code>等,通常使用的是<code>1024bit</code>,私钥格式分为<code>PKCS8</code>和<code>PKCS1</code>,其中<code>PKCS8</code>为<code>java</code>语言中使用的格式,<code>PKCS1</code>为<code>iOS</code>相关语言中使用的格式。</p></li><li><p>通常生成的秘钥会保存在<code>.pem</code>格式的文件中,使用文本编辑器或者代码编辑器打开,可以查看到保存的值,如果是按<code>1024bit</code>取模,<code>PKCS1</code>格式的私钥长度应该是<code>824</code>(包含回车),如果是<code>PKCS8</code>的格式的密钥长度为<code>861</code></p></li><li><p>通常<code>RSA</code>有两种用法,公钥加密私钥解密和私钥签名公钥验签,加密是为了数据保密,签名是为了防恶意攻击,例如防止别人模拟我们的客户端对我们的服务器进行攻击,导致服务器瘫痪等</p></li></ul><h4 id="二、一些在线网站"><a href="#二、一些在线网站" class="headerlink" title="二、一些在线网站"></a>二、一些在线网站</h4><p>有一些网站可以在线生成<code>RSA</code>秘钥,例如<a href="http://web.chacuo.net/netrsakeypair">http://web.chacuo.net/netrsakeypair</a>,这些网站可以便捷的生成私钥,并自动得出相应的公钥,以及能在线转换格式,加密解密等</p><h4 id="三、命令行生成命令"><a href="#三、命令行生成命令" class="headerlink" title="三、命令行生成命令"></a>三、命令行生成命令</h4><p>我们先了解下一个软件包<code>OpenSSL</code>,<code>OpenSSL</code>是为网络通信提供安全及数据完整性的一种安全协议,囊括了主要的密码算法、常用的密钥和证书封装管理功能以及<code>SSL</code>协议,并提供了丰富的应用程序供测试或其它目的使用。<code>LibreSSL</code>是<code>OpenSSL</code>加密软件库的一个分支。在<code>OpenSS</code>L爆出安全漏洞之后,于2014年4月创立,目标是重构<code>OpenSSL</code>的代码,以提供一个更安全的替代品。所以通过在电脑上安装<code>OpenSSL</code>或者<code>LibreSSL</code>后,即可通过相关的命令行生成秘钥。<code>mac</code>电脑已自带<code>LibreSSL</code>,如果没有,可以寻找相关的安装方法,此处不再扩展</p><h5 id="1、基础生成命令"><a href="#1、基础生成命令" class="headerlink" title="1、基础生成命令"></a>1、基础生成命令</h5><ol><li>生成模长为<code>1024bit</code>的私钥</li></ol><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">$ openssl genrsa -out <span class="hljs-regexp">/xx/</span>xx/private_pkcs1.pem <span class="hljs-number">1024</span><br></code></pre></td></tr></table></figure><p><code>private_pkcs1.pem</code>前为本地路径,<code>pem</code>文件会生成到制定目录,长度<code>824</code>,此命令行生成的为<code>PKCS1</code>格式的私钥,如下</p><figure class="highlight awk"><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></pre></td><td class="code"><pre><code class="hljs awk">-----<span class="hljs-keyword">BEGIN</span> RSA PRIVATE KEY-----<br>MIICXgIBAAKBgQDWa6g5OgPyB5xCkvEIitA1gKOBoQi21nAVJL7iVMqkA2MrhmUl<br>ZonITpqMW3syTtaksMualat1CmqJRQaDn+UVe0u2Wgtvvu8KaDdbDa6Tyq6S2K89<br>GI2l/AzouLE06daaHDh3qjtwNmEDqsK7mEcSPddIKaIOHZ7bKzOkbYnGEwIDAQAB<br>AoGBAIiOY8KeaijYI<span class="hljs-regexp">/JaNtuj3FpWpMtHzY70Hsm4b0EhkzTFW4E6xGv/</span>U7yYIuFE<br><span class="hljs-number">2</span>b7+asDUP7chnuKZUaQ+q5lkWbYcKsSWORgGBUeYUOVoU9SuTp65oFKkc9AOtaxz<br>VavX536Y1VRtT+b8mB++gZwp5cZHUbJTj4BPSKH7IJawKskRAkEA7jA4c+I3ZfFD<br>koOl41x3cvwH+xQLi6vpL6Gw3/muJrc6mtdZbcuXwjMYlac++mXPTUt1K4b1sUmG<br>G3qwnkUjXwJBAOZ0b2fZhRhsDzNFihnD1PXGNl56FVG3G0aWZzQIHQX1DIE+sG4k<br>CJxrqxTnHWc+O2ODPU2PbJUN0fcpEuoDbc0CQQC9LpWYDUP89yy5cVDQDgBd1qos<br>FRa6f/d9Ooq2yqQ04fFtTMAeAcfumhDbxHO0BCsr9FQDF3WLs58NslwXyUg3AkBg<br>GK1b4JhfVq<span class="hljs-regexp">//</span><span class="hljs-number">8</span>T9k<span class="hljs-regexp">/wQOeFizjLTXHkOBa7YdPETd9xD/</span><span class="hljs-number">0</span>+Q+CUiN8Veln7njE1Aw<br>bslhTi04+kpThg0dB9EBAkEAiWIlUGra4M5q7u+FWbgtcJRKjMX6LIlsB1UiFHba<br>auSSQGwP+LMHVYDaWljzcPO<span class="hljs-regexp">/c5/</span>MZbIDmGCZsDeImvSdMQ==<br>-----<span class="hljs-keyword">END</span> RSA PRIVATE KEY-----<br></code></pre></td></tr></table></figure><ol start="2"><li><code>PKCS1</code>和<code>PKCS8</code>互相转换</li></ol><figure class="highlight awk"><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><code class="hljs awk"><span class="hljs-regexp">//</span> PKCS1私钥转换为PKCS8,java语言使用的是PKCS8<br>$ openssl pkcs8 -topk8 -inform PEM -<span class="hljs-keyword">in</span> <span class="hljs-regexp">/xx/</span>xx<span class="hljs-regexp">/private_pkcs1.pem -outform pem -nocrypt -out /</span>xx<span class="hljs-regexp">/xx/</span>private_pkcs8.pem<br><br><span class="hljs-regexp">//</span> PKCS8私钥转换为PKCS1<br>$ openssl rsa -<span class="hljs-keyword">in</span> <span class="hljs-regexp">/xx/</span>xx<span class="hljs-regexp">/private_pkcs8.pem -out /</span>xx<span class="hljs-regexp">/xx/</span>private_pkcs1.pem<br></code></pre></td></tr></table></figure><p>同样文件名之前为本地路径,生成到对应的路径下,生成的<code>PKCS8</code>格式私钥如下</p><figure class="highlight awk"><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><code class="hljs awk">-----<span class="hljs-keyword">BEGIN</span> PRIVATE KEY-----<br>MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANZrqDk6A/IHnEKS<br><span class="hljs-number">8</span>QiK0DWAo4GhCLbWcBUkvuJUyqQDYyuGZSVmichOmoxbezJO1qSwy5qVq3UKaolF<br>BoOf5RV7S7ZaC2++<span class="hljs-number">7</span>wpoN1sNrpPKrpLYrz0YjaX8DOi4sTTp1pocOHeqO3A2YQOq<br>wruYRxI910gpog4dntsrM6RticYTAgMBAAECgYEAiI5jwp5qKNgj8lo226PcWlak<br>y0fNjvQeybhvQSGTNMVbgTrEa<span class="hljs-regexp">/9TvJgi4UTZvv5qwNQ/</span>tyGe4plRpD6rmWRZthwq<br>xJY5GAYFR5hQ5WhT1K5OnrmgUqRz0A61rHNVq9fnfpjVVG1P5vyYH76BnCnlxkdR<br>slOPgE9IofsglrAqyRECQQDuMDhz4jdl8UOSg6XjXHdy/Af7FAuLq+kvobDf+a4m<br>tzqa11lty5fCMxiVpz76Zc9NS3UrhvWxSYYberCeRSNfAkEA5nRvZ9mFGGwPM0WK<br>GcPU9cY2XnoVUbcbRpZnNAgdBfUMgT6wbiQInGurFOcdZz47Y4M9TY9slQ3R9ykS<br><span class="hljs-number">6</span>gNtzQJBAL0ulZgNQ<span class="hljs-regexp">/z3LLlxUNAOAF3WqiwVFrp/</span><span class="hljs-number">9306</span>irbKpDTh8W1MwB4Bx+<span class="hljs-number">6</span>a<br>ENvEc7QEKyv0VAMXdYuznw2yXBfJSDcCQGAYrVvgmF9Wr<span class="hljs-regexp">//</span>xP2T/BA54WLOMtNce<br>Q4Frth08RN33EP/T5D4JSI3xV6WfueMTUDBuyWFOLTj6SlOGDR0H0QECQQCJYiVQ<br>atrgzmru74VZuC1wlEqMxfosiWwHVSIUdtpq5JJAbA/<span class="hljs-number">4</span>swdVgNpaWPNw879zn8xl<br>sgOYYJmwN4ia9J0x<br>-----<span class="hljs-keyword">END</span> PRIVATE KEY-----<br></code></pre></td></tr></table></figure><ol start="3"><li>生成公钥</li></ol><p><code>RSA</code>公钥是由私钥中生成的,公钥不区分格式,<code>PKCS1</code>和<code>PKCS8</code>都能生成公钥,生成结果一致</p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs gradle">$ openssl rsa -in <span class="hljs-regexp">/xx/</span>xx<span class="hljs-regexp">/private_pkcs1.pem -pubout -out /</span>xx<span class="hljs-regexp">/xx/</span><span class="hljs-keyword">public</span>.pem<br></code></pre></td></tr></table></figure><p>生成结果如下</p><figure class="highlight vbnet"><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><code class="hljs vbnet">-----BEGIN <span class="hljs-keyword">PUBLIC</span> <span class="hljs-keyword">KEY</span>-----<br>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDWa6g5OgPyB5xCkvEIitA1gKOB<br>oQi21nAVJL7iVMqkA2MrhmUlZonITpqMW3syTtaksMualat1CmqJRQaDn+UVe0u2<br>Wgtvvu8KaDdbDa6Tyq6S2K89GI2l/AzouLE06daaHDh3qjtwNmEDqsK7mEcSPddI<br>KaIOHZ7bKzOkbYnGEwIDAQAB<br>-----<span class="hljs-keyword">END</span> <span class="hljs-keyword">PUBLIC</span> <span class="hljs-keyword">KEY</span>-----<br></code></pre></td></tr></table></figure><blockquote><p>以上为生成<code>RSA</code>秘钥基本的操作,所有的秘钥文件均以<code>.pem</code>格式存在,可以直接使用文本编辑器读取其中的秘钥字符串,秘钥字符串为<code>Base64</code>格式,<code>Android</code>和<code>iOS</code>在使用时都可以直接使用文件或者字符串</p></blockquote><h5 id="2、iOS数字证书"><a href="#2、iOS数字证书" class="headerlink" title="2、iOS数字证书"></a>2、<code>iOS</code>数字证书</h5><p><code>.pem</code>格式文件已能正常使用,<code>iOS</code>系统也可以直接使用文件中的秘钥字符串,为了进一步保证安全性,<code>iOS</code>系统中可以对公钥和私钥进行进一步签名,做成数字证书的形式,<code>.der</code>格式文件存放,<code>.p12</code>格式的文件存放的是私钥,<code>.der</code>和<code>.p12</code>文件均为二进制文件,无法查看</p><ol><li>生成证书请求文件<code>.csr</code></li></ol><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs gradle">$ openssl req -<span class="hljs-keyword">new</span> -key <span class="hljs-regexp">/xxx/</span>xxx<span class="hljs-regexp">/private_pkcs1.pem -out /</span>xxx<span class="hljs-regexp">/xxx/</span>rsa_cert.csr<br></code></pre></td></tr></table></figure><p>这一步会提示输入国家、省份等信息,可酌情填写</p><ol start="2"><li>生成证书<code>.crt</code>,并设置有效时间1年</li></ol><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">$ openssl x509 -req -days <span class="hljs-number">365</span> -<span class="hljs-keyword">in</span> <span class="hljs-regexp">/xxx/</span>xxx<span class="hljs-regexp">/rsa_cert.csr -signkey /</span>xxx<span class="hljs-regexp">/xxx/</span>private_pkcs1.pem -out <span class="hljs-regexp">/xxx/</span>xxx/rsa_cert.crt<br></code></pre></td></tr></table></figure><ol start="3"><li>导出<code>iOS</code>使用的公钥文件<code>.der</code></li></ol><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs gradle">$ openssl x509 -outform der -in <span class="hljs-regexp">/xxx/</span>xxx<span class="hljs-regexp">/rsa_cert.crt -out /</span>xxx<span class="hljs-regexp">/xxx/</span><span class="hljs-keyword">public</span>.der<br></code></pre></td></tr></table></figure><ol start="4"><li>导出<code>iOS</code>使用的私钥文件<code>.p12</code></li></ol><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">$ openssl pkcs12 -export -out <span class="hljs-regexp">/xxx/</span>xxx<span class="hljs-regexp">/private.p12 -inkey /</span>xxx<span class="hljs-regexp">/xxx/</span>private_pkcs1.pem -<span class="hljs-keyword">in</span> <span class="hljs-regexp">/xxx/</span>xxx/rsa_cert.crt<br></code></pre></td></tr></table></figure><p>这一步会提示给私钥证书<code>.p12</code>设置证书密码,输入即可</p><h4 id="四、iOS代码"><a href="#四、iOS代码" class="headerlink" title="四、iOS代码"></a>四、<code>iOS</code>代码</h4><h5 id="1、OpenSSL开源库"><a href="#1、OpenSSL开源库" class="headerlink" title="1、OpenSSL开源库"></a>1、<code>OpenSSL</code>开源库</h5><p><a href="https://github.com/"><code>github</code></a>上有<a href="https://github.com/openssl/openssl"><code>OpenSSL</code></a>的开源代码,但是工程里面无法直接引入,此处推荐另一个开源代码<a href="https://github.com/x2on/OpenSSL-for-iPhone"><code>OpenSSL-for-iPhone</code></a>,在<code>README</code>中作者提供了相关的编译方法</p><p><img src="image_1.png" alt="image_1.png"></p><p>编译完成后,找到<code>OpenSSL-for-iPhone</code>工程里面编译成功的<code>.a</code>文件,<code>libcrypto.a</code>和<code>libssl.a</code>,还有文件夹<code>include</code></p><p><img src="image_2.png" alt="image_2.png"></p><p>导入项目工程中,并把<code>include</code>文件夹添加到<code>Build Setting</code>中的<code>Header Search Paths</code>中,再检查<code>Library Search Paths</code>中是否能引用到<code>.a</code>文件,具体代码如下</p><figure class="highlight objectivec"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br></pre></td><td class="code"><pre><code class="hljs objectivec"><span class="hljs-meta">#import <span class="hljs-meta-string"><Foundation/Foundation.h></span></span><br><span class="hljs-meta">#import <span class="hljs-meta-string"><openssl/rsa.h></span></span><br><br><span class="hljs-built_in">NS_ASSUME_NONNULL_BEGIN</span><br><br><span class="hljs-keyword">typedef</span> <span class="hljs-keyword">enum</span> : <span class="hljs-built_in">NSUInteger</span> {<br> OpenSSL_RSA_SignType_MD5,<br> OpenSSL_RSA_SignType_SHA1,<br> OpenSSL_RSA_SignType_SHA224,<br> OpenSSL_RSA_SignType_SHA256,<br> OpenSSL_RSA_SignType_SHA384,<br> OpenSSL_RSA_SignType_SHA512,<br>} OpenSSL_RSA_SignType;<br><br><span class="hljs-class"><span class="hljs-keyword">@interface</span> <span class="hljs-title">OpenSSLWrapper</span> : <span class="hljs-title">NSObject</span></span><br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 生成一对秘钥</span><br><span class="hljs-comment"></span><br><span class="hljs-comment"> @param keySize 512、1024、2048</span><br><span class="hljs-comment"> @param publicKey 公钥内存地址</span><br><span class="hljs-comment"> @param privateKey 私钥内存地址</span><br><span class="hljs-comment"> @return 是否成功生成</span><br><span class="hljs-comment"> */</span><br>+ (<span class="hljs-built_in">BOOL</span>)generateKeyPairWithKeySize:(<span class="hljs-keyword">int</span>)keySize publicKey:(RSA *_Nullable*_Nullable)publicKey privateKey:(RSA *_Nullable*_Nullable)privateKey;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 公钥加密</span><br><span class="hljs-comment"></span><br><span class="hljs-comment"> @param publicKey 公钥</span><br><span class="hljs-comment"> @param plainString 源数据</span><br><span class="hljs-comment"> @return 加密后数据</span><br><span class="hljs-comment"> */</span><br>+ (<span class="hljs-built_in">NSString</span> *)opensslEncryptWithPublicKey:(RSA *)publicKey plainString:(<span class="hljs-built_in">NSString</span> *)plainString;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 私钥解密</span><br><span class="hljs-comment"></span><br><span class="hljs-comment"> @param privateKey 私钥</span><br><span class="hljs-comment"> @param encryptString 加密后数据</span><br><span class="hljs-comment"> @return 源数据</span><br><span class="hljs-comment"> */</span><br>+ (<span class="hljs-built_in">NSString</span> *)opensslDecryptWithPrivateKey:(RSA *)privateKey encryptString:(<span class="hljs-built_in">NSString</span> *)encryptString;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 私钥签名</span><br><span class="hljs-comment"></span><br><span class="hljs-comment"> @param privateKey 私钥</span><br><span class="hljs-comment"> @param signType 签名算法</span><br><span class="hljs-comment"> @param plainString 源数据</span><br><span class="hljs-comment"> @return 签名后数据</span><br><span class="hljs-comment"> */</span><br>+ (<span class="hljs-built_in">NSString</span> *)signWithPrivateKey:(RSA *)privateKey signType:(OpenSSL_RSA_SignType)signType plainString:(<span class="hljs-built_in">NSString</span> *)plainString;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 公钥验证签名</span><br><span class="hljs-comment"></span><br><span class="hljs-comment"> @param publicKey 公钥</span><br><span class="hljs-comment"> @param signType 签名算法</span><br><span class="hljs-comment"> @param plainString 源数据</span><br><span class="hljs-comment"> @param signString 签名后数据</span><br><span class="hljs-comment"> @return 是否验证成功</span><br><span class="hljs-comment"> */</span><br>+ (<span class="hljs-built_in">BOOL</span>)verifyWithPublicKey:(RSA *)publicKey signType:(OpenSSL_RSA_SignType)signType plainString:(<span class="hljs-built_in">NSString</span> *)plainString signString:(<span class="hljs-built_in">NSString</span> *)signString;<br><br><span class="hljs-comment">// RSA转base64</span><br>+ (<span class="hljs-built_in">NSString</span> *)base64StringFromPublicRSAKey:(RSA *)rsaKey;<br>+ (<span class="hljs-built_in">NSString</span> *)base64StringFromPrivateRSAKey:(RSA *)rsaKey;<br><span class="hljs-comment">// base64转RSA秘钥</span><br>+ (RSA *)publicRSAKeyFromBase64String:(<span class="hljs-built_in">NSString</span> *)keyString;<br>+ (RSA *)privateRSAKeyFromBase64String:(<span class="hljs-built_in">NSString</span> *)keyString;<br><br><span class="hljs-keyword">@end</span><br><br><span class="hljs-built_in">NS_ASSUME_NONNULL_END</span><br></code></pre></td></tr></table></figure><figure class="highlight objectivec"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br></pre></td><td class="code"><pre><code class="hljs objectivec"><span class="hljs-meta">#import <span class="hljs-meta-string">"OpenSSLWrapper.h"</span></span><br><span class="hljs-meta">#import <span class="hljs-meta-string"><openssl/pem.h></span></span><br><span class="hljs-meta">#import <span class="hljs-meta-string"><CommonCrypto/CommonCrypto.h></span></span><br><br><span class="hljs-class"><span class="hljs-keyword">@implementation</span> <span class="hljs-title">OpenSSLWrapper</span></span><br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 生成一对秘钥</span><br><span class="hljs-comment"> */</span><br>+ (<span class="hljs-built_in">BOOL</span>)generateKeyPairWithKeySize:(<span class="hljs-keyword">int</span>)keySize publicKey:(RSA *_Nullable*_Nullable)publicKey privateKey:(RSA *_Nullable*_Nullable)privateKey {<br> <span class="hljs-keyword">if</span> (keySize == <span class="hljs-number">512</span> || keySize == <span class="hljs-number">1024</span> || keySize == <span class="hljs-number">2048</span>) {<br> RSA *rsa = RSA_generate_key(keySize, RSA_F4, <span class="hljs-literal">NULL</span>, <span class="hljs-literal">NULL</span>);<br> <span class="hljs-keyword">if</span> (rsa) {<br> *privateKey = RSAPrivateKey_dup(rsa);<br> *publicKey = RSAPublicKey_dup(rsa);<br> <span class="hljs-keyword">if</span> (*privateKey && *publicKey) {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">YES</span>;<br> }<br> }<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">NO</span>;<br>}<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 公钥加密</span><br><span class="hljs-comment"> */</span><br>+ (<span class="hljs-built_in">NSString</span> *)opensslEncryptWithPublicKey:(RSA *)publicKey plainString:(<span class="hljs-built_in">NSString</span> *)plainString {<br> <span class="hljs-comment">// 参数转data</span><br> <span class="hljs-built_in">NSData</span> *plainData = [plainString dataUsingEncoding:<span class="hljs-built_in">NSUTF8StringEncoding</span>];<br> <span class="hljs-built_in">NSMutableData</span> *encryptData = [<span class="hljs-built_in">NSMutableData</span> data];<br> <span class="hljs-comment">// 分段加密,计算分段长度</span><br> <span class="hljs-keyword">int</span> cipherBufferSize = RSA_size(publicKey);<br> <span class="hljs-built_in">NSUInteger</span> totalSize = plainData.length;<br> <br> <span class="hljs-keyword">int</span> blockSize = cipherBufferSize - RSA_PKCS1_PADDING_SIZE;<br> <span class="hljs-keyword">int</span> blockCount = ceil(totalSize * <span class="hljs-number">1.</span>f / blockSize);<br> <br> <span class="hljs-comment">// 遍历获取每个分段数据</span><br> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < blockCount; i++) {<br> <span class="hljs-comment">// 取出当前分段数据</span><br> <span class="hljs-built_in">NSData</span> *blockData;<br> <span class="hljs-keyword">if</span> (i < (blockCount - <span class="hljs-number">1</span>)) {<br> blockData = [plainData subdataWithRange:<span class="hljs-built_in">NSMakeRange</span>(i * blockSize, blockSize)];<br> } <span class="hljs-keyword">else</span> {<br> blockData = [plainData subdataWithRange:<span class="hljs-built_in">NSMakeRange</span>(i * blockSize, totalSize - i * blockSize)];<br> }<br> <span class="hljs-comment">// 申请对应内存,公钥长度</span><br> uint8_t *cipherBuffer = malloc(cipherBufferSize * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)cipherBuffer, <span class="hljs-number">0x0</span>, cipherBufferSize);<br> <span class="hljs-comment">// 加密当前分段数据</span><br> <span class="hljs-keyword">int</span> result = RSA_public_encrypt((<span class="hljs-keyword">int</span>)blockData.length, (<span class="hljs-keyword">const</span> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *)blockData.bytes, (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *)cipherBuffer, publicKey, RSA_PKCS1_PADDING);<br> <span class="hljs-keyword">if</span> (result < <span class="hljs-number">0</span>) {<br> <span class="hljs-comment">// 加密失败,释放内存</span><br> <span class="hljs-keyword">if</span> (cipherBuffer) {<br> free(cipherBuffer);<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>;<br> }<br> <span class="hljs-built_in">NSData</span> *cipher = [[<span class="hljs-built_in">NSData</span> alloc] initWithBytes:cipherBuffer length:result];<br> [encryptData appendData:cipher];<br> <span class="hljs-keyword">if</span> (cipherBuffer) {<br> free(cipherBuffer);<br> }<br> }<br> <span class="hljs-comment">// 转base64</span><br> <span class="hljs-built_in">NSString</span> *encryptString = [encryptData base64EncodedStringWithOptions:<span class="hljs-number">0</span>];<br> <span class="hljs-keyword">return</span> encryptString;<br>}<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 私钥解密</span><br><span class="hljs-comment"> */</span><br>+ (<span class="hljs-built_in">NSString</span> *)opensslDecryptWithPrivateKey:(RSA *)privateKey encryptString:(<span class="hljs-built_in">NSString</span> *)encryptString {<br> <span class="hljs-comment">// 参数转data</span><br> <span class="hljs-built_in">NSData</span> *encryptData = [[<span class="hljs-built_in">NSData</span> alloc] initWithBase64EncodedString:encryptString options:<span class="hljs-built_in">NSDataBase64DecodingIgnoreUnknownCharacters</span>];<br> <span class="hljs-built_in">NSMutableData</span> *outputPlainData = [<span class="hljs-built_in">NSMutableData</span> data];<br> <span class="hljs-comment">// 分段解密,计算分段长度</span><br> <span class="hljs-keyword">int</span> cipherBufferSize = RSA_size(privateKey);<br> <span class="hljs-built_in">NSUInteger</span> totalSize = encryptData.length;<br> <br> <span class="hljs-keyword">int</span> blockSize = cipherBufferSize;<br> <span class="hljs-keyword">int</span> blockCount = ceil(totalSize * <span class="hljs-number">1.</span>f / blockSize);<br> <br> <span class="hljs-comment">// 遍历获取每个分段数据</span><br> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < blockCount; i++) {<br> <span class="hljs-comment">// 取出当前分段数据</span><br> <span class="hljs-built_in">NSData</span> *blockData;<br> <span class="hljs-keyword">if</span> (i < (blockCount - <span class="hljs-number">1</span>)) {<br> blockData = [encryptData subdataWithRange:<span class="hljs-built_in">NSMakeRange</span>(i * blockSize, blockSize)];<br> } <span class="hljs-keyword">else</span> {<br> blockData = [encryptData subdataWithRange:<span class="hljs-built_in">NSMakeRange</span>(i * blockSize, totalSize - i * blockSize)];<br> }<br> <span class="hljs-comment">// 申请对应内存</span><br> uint8_t *keyBuffer = malloc(cipherBufferSize * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)keyBuffer, <span class="hljs-number">0x0</span>, cipherBufferSize);<br> <span class="hljs-comment">// 解密当前分段数据</span><br> <span class="hljs-keyword">int</span> result = RSA_private_decrypt(cipherBufferSize, (<span class="hljs-keyword">const</span> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *)blockData.bytes, (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *)keyBuffer, privateKey, RSA_PKCS1_PADDING);<br> <span class="hljs-keyword">if</span> (result < <span class="hljs-number">0</span>) {<br> <span class="hljs-comment">// 解密失败,释放内存</span><br> <span class="hljs-keyword">if</span> (keyBuffer) {<br> free(keyBuffer);<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>;<br> }<br> <span class="hljs-built_in">NSData</span> *key = [[<span class="hljs-built_in">NSData</span> alloc] initWithBytes:keyBuffer length:result];<br> [outputPlainData appendData:key];<br> <span class="hljs-keyword">if</span> (keyBuffer) {<br> free(keyBuffer);<br> }<br> }<br> <span class="hljs-built_in">NSString</span> *outputPlainString = [[<span class="hljs-built_in">NSString</span> alloc] initWithData:outputPlainData encoding:<span class="hljs-built_in">NSUTF8StringEncoding</span>];<br> <span class="hljs-keyword">return</span> outputPlainString;<br>}<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 私钥签名</span><br><span class="hljs-comment"> */</span><br>+ (<span class="hljs-built_in">NSString</span> *)signWithPrivateKey:(RSA *)privateKey signType:(OpenSSL_RSA_SignType)signType plainString:(<span class="hljs-built_in">NSString</span> *)plainString {<br> <span class="hljs-built_in">NSData</span> *plainData = [plainString dataUsingEncoding:(<span class="hljs-built_in">NSUTF8StringEncoding</span>)];<br> <br> <span class="hljs-keyword">int</span> type;<br> <span class="hljs-built_in">NSData</span> *digestData = <span class="hljs-literal">nil</span>;<br> <span class="hljs-keyword">switch</span> (signType) {<br> <span class="hljs-keyword">case</span> OpenSSL_RSA_SignType_MD5:<br> {<br> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> digest[CC_MD5_DIGEST_LENGTH];<br> CC_MD5([plainData bytes], (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span>)[plainData length], digest);<br> digestData = [<span class="hljs-built_in">NSData</span> dataWithBytes:digest length:CC_MD5_DIGEST_LENGTH];<br> type = NID_md5;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> OpenSSL_RSA_SignType_SHA1:<br> {<br> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> digest[CC_SHA1_DIGEST_LENGTH];<br> CC_SHA1([plainData bytes], (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span>)[plainData length], digest);<br> digestData = [<span class="hljs-built_in">NSData</span> dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];<br> type = NID_sha1;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> OpenSSL_RSA_SignType_SHA224:<br> {<br> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> digest[CC_SHA224_DIGEST_LENGTH];<br> CC_SHA224([plainData bytes], (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span>)[plainData length], digest);<br> digestData = [<span class="hljs-built_in">NSData</span> dataWithBytes:digest length:CC_SHA224_DIGEST_LENGTH];<br> type = NID_sha224;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> OpenSSL_RSA_SignType_SHA256:<br> {<br> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> digest[CC_SHA256_DIGEST_LENGTH];<br> CC_SHA256([plainData bytes], (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span>)[plainData length], digest);<br> digestData = [<span class="hljs-built_in">NSData</span> dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH];<br> type = NID_sha256;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> OpenSSL_RSA_SignType_SHA384:<br> {<br> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> digest[CC_SHA384_DIGEST_LENGTH];<br> CC_SHA384([plainData bytes], (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span>)[plainData length], digest);<br> digestData = [<span class="hljs-built_in">NSData</span> dataWithBytes:digest length:CC_SHA384_DIGEST_LENGTH];<br> type = NID_sha384;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> OpenSSL_RSA_SignType_SHA512:<br> {<br> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> digest[CC_SHA512_DIGEST_LENGTH];<br> CC_SHA512([plainData bytes], (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span>)[plainData length], digest);<br> digestData = [<span class="hljs-built_in">NSData</span> dataWithBytes:digest length:CC_SHA512_DIGEST_LENGTH];<br> type = NID_sha512;<br> }<br> <span class="hljs-keyword">break</span>;<br> <br> <span class="hljs-keyword">default</span>:<br> <span class="hljs-keyword">break</span>;<br> }<br> <br> <span class="hljs-keyword">if</span> (digestData) {<br> <span class="hljs-keyword">int</span> signedHashBytesSize = RSA_size(privateKey);<br> <br> uint8_t *signedHashBytes = malloc(signedHashBytesSize * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)signedHashBytes, <span class="hljs-number">0x0</span>, signedHashBytesSize);<br> <br> <br> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span> siglen = <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">int</span> result = RSA_sign(type, (<span class="hljs-keyword">const</span> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *)digestData.bytes, (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span>)digestData.length, (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *)signedHashBytes, &siglen, privateKey);<br> <span class="hljs-keyword">if</span> (result == <span class="hljs-number">1</span>) {<br> <span class="hljs-built_in">NSData</span> *signedHash = [<span class="hljs-built_in">NSData</span> dataWithBytes:signedHashBytes length:siglen];<br> <span class="hljs-keyword">if</span> (signedHashBytes) {<br> free(signedHashBytes);<br> }<br> <span class="hljs-built_in">NSString</span> *signString = [signedHash base64EncodedStringWithOptions:<span class="hljs-number">0</span>];<br> <span class="hljs-keyword">return</span> signString;<br> }<br> <span class="hljs-keyword">if</span> (signedHashBytes) {<br> free(signedHashBytes);<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>;<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>;<br> }<br>}<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 公钥验证签名</span><br><span class="hljs-comment"> */</span><br>+ (<span class="hljs-built_in">BOOL</span>)verifyWithPublicKey:(RSA *)publicKey signType:(OpenSSL_RSA_SignType)signType plainString:(<span class="hljs-built_in">NSString</span> *)plainString signString:(<span class="hljs-built_in">NSString</span> *)signString {<br> <br> <span class="hljs-built_in">NSData</span> *plainData = [plainString dataUsingEncoding:(<span class="hljs-built_in">NSUTF8StringEncoding</span>)];<br> <span class="hljs-built_in">NSData</span> *signData = [[<span class="hljs-built_in">NSData</span> alloc] initWithBase64EncodedString:signString options:<span class="hljs-built_in">NSDataBase64DecodingIgnoreUnknownCharacters</span>];<br> <br> <span class="hljs-keyword">int</span> type;<br> <span class="hljs-built_in">NSData</span> *digestData = <span class="hljs-literal">nil</span>;<br> <span class="hljs-keyword">switch</span> (signType) {<br> <span class="hljs-keyword">case</span> OpenSSL_RSA_SignType_MD5:<br> {<br> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> digest[CC_MD5_DIGEST_LENGTH];<br> CC_MD5([plainData bytes], (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span>)[plainData length], digest);<br> digestData = [<span class="hljs-built_in">NSData</span> dataWithBytes:digest length:CC_MD5_DIGEST_LENGTH];<br> type = NID_md5;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> OpenSSL_RSA_SignType_SHA1:<br> {<br> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> digest[CC_SHA1_DIGEST_LENGTH];<br> CC_SHA1([plainData bytes], (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span>)[plainData length], digest);<br> digestData = [<span class="hljs-built_in">NSData</span> dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];<br> type = NID_sha1;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> OpenSSL_RSA_SignType_SHA224:<br> {<br> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> digest[CC_SHA224_DIGEST_LENGTH];<br> CC_SHA224([plainData bytes], (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span>)[plainData length], digest);<br> digestData = [<span class="hljs-built_in">NSData</span> dataWithBytes:digest length:CC_SHA224_DIGEST_LENGTH];<br> type = NID_sha224;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> OpenSSL_RSA_SignType_SHA256:<br> {<br> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> digest[CC_SHA256_DIGEST_LENGTH];<br> CC_SHA256([plainData bytes], (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span>)[plainData length], digest);<br> digestData = [<span class="hljs-built_in">NSData</span> dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH];<br> type = NID_sha256;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> OpenSSL_RSA_SignType_SHA384:<br> {<br> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> digest[CC_SHA384_DIGEST_LENGTH];<br> CC_SHA384([plainData bytes], (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span>)[plainData length], digest);<br> digestData = [<span class="hljs-built_in">NSData</span> dataWithBytes:digest length:CC_SHA384_DIGEST_LENGTH];<br> type = NID_sha384;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> OpenSSL_RSA_SignType_SHA512:<br> {<br> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> digest[CC_SHA512_DIGEST_LENGTH];<br> CC_SHA512([plainData bytes], (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span>)[plainData length], digest);<br> digestData = [<span class="hljs-built_in">NSData</span> dataWithBytes:digest length:CC_SHA512_DIGEST_LENGTH];<br> type = NID_sha512;<br> }<br> <span class="hljs-keyword">break</span>;<br> <br> <span class="hljs-keyword">default</span>:<br> <span class="hljs-keyword">break</span>;<br> }<br> <br> <span class="hljs-keyword">if</span> (digestData) {<br> <span class="hljs-keyword">int</span> result = RSA_verify(type, (<span class="hljs-keyword">const</span> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *)digestData.bytes, (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span>)digestData.length, (<span class="hljs-keyword">const</span> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *)signData.bytes, (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">int</span>)signData.length, publicKey);<br> <span class="hljs-keyword">if</span> (result == <span class="hljs-number">1</span>) {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">YES</span>;<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">NO</span>;<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">NO</span>;<br> }<br>}<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> RSA转base64</span><br><span class="hljs-comment"> */</span><br>+ (<span class="hljs-built_in">NSString</span> *)base64StringFromPublicRSAKey:(RSA *)rsaKey {<br> BIO *bio = BIO_new(BIO_s_mem());<br> PEM_write_bio_RSA_PUBKEY(bio, rsaKey);<br> BUF_MEM *buf;<br> BIO_get_mem_ptr(bio, &buf);<br> <span class="hljs-comment">// data 后面可能会有有脏数据</span><br> <span class="hljs-built_in">NSString</span> *pemString = [[<span class="hljs-built_in">NSString</span> stringWithFormat:<span class="hljs-string">@"%s"</span>, buf->data] substringToIndex:buf->length];<br> BIO_set_close(bio, BIO_NOCLOSE);<br> BIO_free(bio);<br> <span class="hljs-built_in">NSString</span> *base64 = [[pemString componentsSeparatedByString:<span class="hljs-string">@"-----"</span>] objectAtIndex:<span class="hljs-number">2</span>];<br> <span class="hljs-keyword">return</span> base64;<br>}<br>+ (<span class="hljs-built_in">NSString</span> *)base64StringFromPrivateRSAKey:(RSA *)rsaKey {<br> BIO *bio = BIO_new(BIO_s_mem());<br> PEM_write_bio_RSAPrivateKey(bio, rsaKey, <span class="hljs-literal">NULL</span>, <span class="hljs-literal">NULL</span>, <span class="hljs-number">0</span>, <span class="hljs-literal">NULL</span>, <span class="hljs-literal">NULL</span>);<br> BUF_MEM *buf;<br> BIO_get_mem_ptr(bio, &buf);<br> <span class="hljs-comment">// data 后面可能会有有脏数据</span><br> <span class="hljs-built_in">NSString</span> *pemString = [[<span class="hljs-built_in">NSString</span> stringWithFormat:<span class="hljs-string">@"%s"</span>, buf->data] substringToIndex:buf->length];<br> BIO_set_close(bio, BIO_NOCLOSE);<br> BIO_free(bio);<br> <span class="hljs-built_in">NSString</span> *base64 = [[pemString componentsSeparatedByString:<span class="hljs-string">@"-----"</span>] objectAtIndex:<span class="hljs-number">2</span>];<br> <span class="hljs-keyword">return</span> base64;<br>}<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> base64转RSA秘钥</span><br><span class="hljs-comment"> */</span><br>+ (RSA *)publicRSAKeyFromBase64String:(<span class="hljs-built_in">NSString</span> *)keyString {<br> <span class="hljs-built_in">NSMutableString</span> *result = [<span class="hljs-built_in">NSMutableString</span> string];<br> [result appendString:<span class="hljs-string">@"-----BEGIN PUBLIC KEY-----\n"</span>];<br> <span class="hljs-keyword">int</span> count = <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < keyString.length; i++) {<br> <span class="hljs-keyword">unichar</span> c = [keyString characterAtIndex:i];<br> <span class="hljs-keyword">if</span> (c == <span class="hljs-string">'\n'</span> || c == <span class="hljs-string">'\r'</span>) {<br> <span class="hljs-keyword">continue</span>;<br> }<br> [result appendFormat:<span class="hljs-string">@"%c"</span>, c];<br> count++;<br> <span class="hljs-keyword">if</span> (count == <span class="hljs-number">64</span>) {<br> [result appendString:<span class="hljs-string">@"\n"</span>];<br> count = <span class="hljs-number">0</span>;<br> }<br> }<br> [result appendString:<span class="hljs-string">@"\n-----END PUBLIC KEY-----"</span>];<br> <br> <span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *buffer = [result UTF8String];<br> BIO *bio = BIO_new_mem_buf(buffer, (<span class="hljs-keyword">int</span>)strlen(buffer));<br> RSA *publicKey = PEM_read_bio_RSA_PUBKEY(bio, <span class="hljs-literal">NULL</span>, <span class="hljs-literal">NULL</span>, <span class="hljs-literal">NULL</span>);<br> BIO_free_all(bio);<br> <span class="hljs-keyword">return</span> publicKey;<br>}<br><br>+ (RSA *)privateRSAKeyFromBase64String:(<span class="hljs-built_in">NSString</span> *)keyString {<br> <span class="hljs-built_in">NSMutableString</span> *result = [<span class="hljs-built_in">NSMutableString</span> string];<br> [result appendString:<span class="hljs-string">@"-----BEGIN RSA PRIVATE KEY-----\n"</span>];<br> <span class="hljs-keyword">int</span> count = <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < keyString.length; i++) {<br> <span class="hljs-keyword">unichar</span> c = [keyString characterAtIndex:i];<br> <span class="hljs-keyword">if</span> (c == <span class="hljs-string">'\n'</span> || c == <span class="hljs-string">'\r'</span>) {<br> <span class="hljs-keyword">continue</span>;<br> }<br> [result appendFormat:<span class="hljs-string">@"%c"</span>, c];<br> count++;<br> <span class="hljs-keyword">if</span> (count == <span class="hljs-number">64</span>) {<br> [result appendString:<span class="hljs-string">@"\n"</span>];<br> count = <span class="hljs-number">0</span>;<br> }<br> }<br> [result appendString:<span class="hljs-string">@"\n-----END RSA PRIVATE KEY-----"</span>];<br> <br> <span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *buffer = [result UTF8String];<br> BIO *bio = BIO_new_mem_buf(buffer, (<span class="hljs-keyword">int</span>)strlen(buffer));<br> RSA *privateKey = PEM_read_bio_RSAPrivateKey(bio, <span class="hljs-literal">NULL</span>, <span class="hljs-literal">NULL</span>, <span class="hljs-literal">NULL</span>);<br> BIO_free_all(bio);<br> <span class="hljs-keyword">return</span> privateKey;<br>}<br><br><span class="hljs-keyword">@end</span><br></code></pre></td></tr></table></figure><p>方法调用示例:</p><figure class="highlight objectivec"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><code class="hljs objectivec"><span class="hljs-meta">#import <span class="hljs-meta-string">"ViewController.h"</span></span><br><span class="hljs-meta">#import <span class="hljs-meta-string">"OpenSSLWrapper.h"</span></span><br><br><span class="hljs-class"><span class="hljs-keyword">@interface</span> <span class="hljs-title">ViewController</span> () </span>{<br> RSA *_publicKey;<br> RSA *_privateKey;<br>}<br><span class="hljs-keyword">@end</span><br><br><span class="hljs-class"><span class="hljs-keyword">@implementation</span> <span class="hljs-title">ViewController</span></span><br><br>- (<span class="hljs-keyword">void</span>)viewDidLoad {<br> [<span class="hljs-keyword">super</span> viewDidLoad];<br> <span class="hljs-comment">// Do any additional setup after loading the view.</span><br> <br> _publicKey = <span class="hljs-literal">NULL</span>;<br> _privateKey = <span class="hljs-literal">NULL</span>;<br> [OpenSSLWrapper generateKeyPairWithKeySize:<span class="hljs-number">1024</span> publicKey:&_publicKey privateKey:&_privateKey];<br> <span class="hljs-built_in">NSString</span> *publicKeyBase64 = [OpenSSLWrapper base64StringFromPublicRSAKey:_publicKey];<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"公钥:%@"</span>, publicKeyBase64);<br> <span class="hljs-built_in">NSString</span> *privateKeyBase64 = [OpenSSLWrapper base64StringFromPrivateRSAKey:_privateKey];<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"私钥:%@"</span>, privateKeyBase64);<br><br> <span class="hljs-built_in">NSString</span> *plainString = <span class="hljs-string">@"123qweQWE测试@#%&*"</span>;<br><br> <span class="hljs-built_in">NSString</span> *encryptedString = [OpenSSLWrapper opensslEncryptWithPublicKey:_publicKey plainString:plainString];<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"%@"</span>, [<span class="hljs-built_in">NSString</span> stringWithFormat:<span class="hljs-string">@"公钥加密:%@"</span>, encryptedString]);<br><br> <span class="hljs-built_in">NSString</span> *outputPlainString = [OpenSSLWrapper opensslDecryptWithPrivateKey:_privateKey encryptString:encryptedString];<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"%@"</span>, [<span class="hljs-built_in">NSString</span> stringWithFormat:<span class="hljs-string">@"私钥解密:%@"</span>, outputPlainString]);<br><br> <span class="hljs-built_in">NSString</span> *signString = [OpenSSLWrapper signWithPrivateKey:_privateKey signType:(OpenSSL_RSA_SignType_SHA1) plainString:plainString];<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"%@"</span>, [<span class="hljs-built_in">NSString</span> stringWithFormat:<span class="hljs-string">@"私钥签名:%@"</span>, signString]);<br><br> <span class="hljs-built_in">BOOL</span> verify = [OpenSSLWrapper verifyWithPublicKey:_publicKey signType:(OpenSSL_RSA_SignType_SHA1) plainString:plainString signString:signString];<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"%@"</span>, [<span class="hljs-built_in">NSString</span> stringWithFormat:<span class="hljs-string">@"验证 %@"</span>, verify ? <span class="hljs-string">@"通过"</span> : <span class="hljs-string">@"不通过"</span>]);<br>}<br><br><span class="hljs-keyword">@end</span><br></code></pre></td></tr></table></figure><h5 id="2、苹果官方Security库"><a href="#2、苹果官方Security库" class="headerlink" title="2、苹果官方Security库"></a>2、苹果官方<code>Security</code>库</h5><p>苹果官方<code>Security</code>库也集成了相应的方法,在<code>iOS 2</code>中便已经提供,官网也提供了调用示例代码,苹果系统打包和发布均采用了<code>RSA</code>的操作</p><blockquote><div style="color: red;">注:部分新的方法在`iOS 10.0`系统后提供</div></blockquote><figure class="highlight objectivec"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br></pre></td><td class="code"><pre><code class="hljs objectivec"><span class="hljs-meta">#import <span class="hljs-meta-string"><Foundation/Foundation.h></span></span><br><span class="hljs-meta">#import <span class="hljs-meta-string"><Security/Security.h></span></span><br><br><span class="hljs-built_in">NS_ASSUME_NONNULL_BEGIN</span><br><br><span class="hljs-class"><span class="hljs-keyword">@interface</span> <span class="hljs-title">SecKeyWrapper</span> : <span class="hljs-title">NSObject</span> <<span class="hljs-title">NSCopying</span>, <span class="hljs-title">NSMutableCopying</span>></span><br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 单例方法</span><br><span class="hljs-comment"> */</span><br>+ (<span class="hljs-keyword">instancetype</span>)shareInstance;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 生成秘钥</span><br><span class="hljs-comment"></span><br><span class="hljs-comment"> @param keySize 512、1024、2048</span><br><span class="hljs-comment"> @param publicKeyRef 公钥内存地址</span><br><span class="hljs-comment"> @param privateKeyRef 公钥内存地址</span><br><span class="hljs-comment"> @return 是否成功生成</span><br><span class="hljs-comment"> */</span><br>- (<span class="hljs-built_in">BOOL</span>)generateKeyPair:(<span class="hljs-built_in">NSUInteger</span>)keySize publicKey:(SecKeyRef _Nullable *_Nonnull)publicKeyRef privateKey:(SecKeyRef _Nullable *_Nonnull)privateKeyRef;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 公钥加密</span><br><span class="hljs-comment"> </span><br><span class="hljs-comment"> @param publicKey 公钥</span><br><span class="hljs-comment"> @param plainString 源数据</span><br><span class="hljs-comment"> @return 加密后数据</span><br><span class="hljs-comment"> */</span><br>- (<span class="hljs-built_in">NSString</span> *)secKeyEncryptWithPublicKey:(SecKeyRef)publicKey plainString:(<span class="hljs-built_in">NSString</span> *)plainString;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 私钥解密</span><br><span class="hljs-comment"> </span><br><span class="hljs-comment"> @param privateKey 私钥</span><br><span class="hljs-comment"> @param encryptString 加密后数据</span><br><span class="hljs-comment"> @return 源数据</span><br><span class="hljs-comment"> */</span><br>- (<span class="hljs-built_in">NSString</span> *)secKeyDecryptWithPrivateKey:(SecKeyRef)privateKey encryptString:(<span class="hljs-built_in">NSString</span> *)encryptString;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 私钥签名</span><br><span class="hljs-comment"> </span><br><span class="hljs-comment"> @param privateKey 私钥</span><br><span class="hljs-comment"> @param secPadding 算法类型</span><br><span class="hljs-comment"> @param plainString 源数据</span><br><span class="hljs-comment"> @return 签名后数据</span><br><span class="hljs-comment"> */</span><br>- (<span class="hljs-built_in">NSString</span> *)signWithPrivateSecKey:(SecKeyRef)privateKey secPadding:(SecPadding)secPadding plainString:(<span class="hljs-built_in">NSString</span> *)plainString;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 公钥验证签名</span><br><span class="hljs-comment"> </span><br><span class="hljs-comment"> @param publicKey 公钥</span><br><span class="hljs-comment"> @param secPadding 算法类型</span><br><span class="hljs-comment"> @param plainString 源数据</span><br><span class="hljs-comment"> @param signString 签名后数据</span><br><span class="hljs-comment"> @return 是否验证成功</span><br><span class="hljs-comment"> */</span><br>- (<span class="hljs-built_in">BOOL</span>)verifyWithPublicSecKey:(SecKeyRef)publicKey secPadding:(SecPadding)secPadding plainString:(<span class="hljs-built_in">NSString</span> *)plainString signString:(<span class="hljs-built_in">NSString</span> *)signString;<br><br><span class="hljs-meta">#<span class="hljs-meta-keyword">if</span> __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0</span><br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> SecKeyRef转base64</span><br><span class="hljs-comment"> */</span><br>- (<span class="hljs-built_in">NSString</span> *)base64StringFromSecKey:(SecKeyRef)secKey;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> base64转SecKeyRef</span><br><span class="hljs-comment"> */</span><br>- (SecKeyRef)publicSecKeyFromBase64String:(<span class="hljs-built_in">NSString</span> *)keyString;<br>- (SecKeyRef)privateSecKeyFromBase64String:(<span class="hljs-built_in">NSString</span> *)keyString;<br><br><span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span><br><br><span class="hljs-keyword">@end</span><br><br><span class="hljs-built_in">NS_ASSUME_NONNULL_END</span><br></code></pre></td></tr></table></figure><figure class="highlight objectivec"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br><span class="line">436</span><br><span class="line">437</span><br><span class="line">438</span><br><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br><span class="line">452</span><br><span class="line">453</span><br><span class="line">454</span><br><span class="line">455</span><br><span class="line">456</span><br><span class="line">457</span><br><span class="line">458</span><br><span class="line">459</span><br><span class="line">460</span><br><span class="line">461</span><br><span class="line">462</span><br><span class="line">463</span><br><span class="line">464</span><br><span class="line">465</span><br><span class="line">466</span><br><span class="line">467</span><br><span class="line">468</span><br><span class="line">469</span><br><span class="line">470</span><br><span class="line">471</span><br><span class="line">472</span><br><span class="line">473</span><br><span class="line">474</span><br><span class="line">475</span><br><span class="line">476</span><br><span class="line">477</span><br><span class="line">478</span><br><span class="line">479</span><br><span class="line">480</span><br><span class="line">481</span><br><span class="line">482</span><br><span class="line">483</span><br><span class="line">484</span><br><span class="line">485</span><br><span class="line">486</span><br><span class="line">487</span><br><span class="line">488</span><br><span class="line">489</span><br><span class="line">490</span><br><span class="line">491</span><br><span class="line">492</span><br><span class="line">493</span><br><span class="line">494</span><br><span class="line">495</span><br><span class="line">496</span><br><span class="line">497</span><br><span class="line">498</span><br><span class="line">499</span><br><span class="line">500</span><br><span class="line">501</span><br><span class="line">502</span><br><span class="line">503</span><br><span class="line">504</span><br><span class="line">505</span><br><span class="line">506</span><br><span class="line">507</span><br><span class="line">508</span><br><span class="line">509</span><br><span class="line">510</span><br><span class="line">511</span><br><span class="line">512</span><br><span class="line">513</span><br><span class="line">514</span><br><span class="line">515</span><br><span class="line">516</span><br><span class="line">517</span><br><span class="line">518</span><br><span class="line">519</span><br><span class="line">520</span><br><span class="line">521</span><br><span class="line">522</span><br><span class="line">523</span><br><span class="line">524</span><br><span class="line">525</span><br><span class="line">526</span><br><span class="line">527</span><br><span class="line">528</span><br><span class="line">529</span><br><span class="line">530</span><br><span class="line">531</span><br><span class="line">532</span><br><span class="line">533</span><br><span class="line">534</span><br><span class="line">535</span><br><span class="line">536</span><br><span class="line">537</span><br><span class="line">538</span><br><span class="line">539</span><br><span class="line">540</span><br><span class="line">541</span><br><span class="line">542</span><br><span class="line">543</span><br><span class="line">544</span><br><span class="line">545</span><br><span class="line">546</span><br><span class="line">547</span><br><span class="line">548</span><br><span class="line">549</span><br><span class="line">550</span><br><span class="line">551</span><br><span class="line">552</span><br><span class="line">553</span><br><span class="line">554</span><br><span class="line">555</span><br><span class="line">556</span><br><span class="line">557</span><br><span class="line">558</span><br><span class="line">559</span><br><span class="line">560</span><br><span class="line">561</span><br><span class="line">562</span><br><span class="line">563</span><br><span class="line">564</span><br><span class="line">565</span><br><span class="line">566</span><br><span class="line">567</span><br><span class="line">568</span><br><span class="line">569</span><br><span class="line">570</span><br><span class="line">571</span><br><span class="line">572</span><br><span class="line">573</span><br><span class="line">574</span><br><span class="line">575</span><br><span class="line">576</span><br><span class="line">577</span><br><span class="line">578</span><br><span class="line">579</span><br><span class="line">580</span><br><span class="line">581</span><br><span class="line">582</span><br><span class="line">583</span><br><span class="line">584</span><br><span class="line">585</span><br><span class="line">586</span><br><span class="line">587</span><br><span class="line">588</span><br><span class="line">589</span><br><span class="line">590</span><br><span class="line">591</span><br><span class="line">592</span><br><span class="line">593</span><br><span class="line">594</span><br><span class="line">595</span><br><span class="line">596</span><br><span class="line">597</span><br><span class="line">598</span><br><span class="line">599</span><br><span class="line">600</span><br><span class="line">601</span><br><span class="line">602</span><br><span class="line">603</span><br><span class="line">604</span><br><span class="line">605</span><br><span class="line">606</span><br><span class="line">607</span><br><span class="line">608</span><br><span class="line">609</span><br><span class="line">610</span><br><span class="line">611</span><br><span class="line">612</span><br><span class="line">613</span><br><span class="line">614</span><br><span class="line">615</span><br><span class="line">616</span><br><span class="line">617</span><br><span class="line">618</span><br><span class="line">619</span><br><span class="line">620</span><br><span class="line">621</span><br><span class="line">622</span><br><span class="line">623</span><br><span class="line">624</span><br><span class="line">625</span><br><span class="line">626</span><br><span class="line">627</span><br><span class="line">628</span><br><span class="line">629</span><br><span class="line">630</span><br><span class="line">631</span><br><span class="line">632</span><br><span class="line">633</span><br><span class="line">634</span><br><span class="line">635</span><br><span class="line">636</span><br><span class="line">637</span><br><span class="line">638</span><br><span class="line">639</span><br><span class="line">640</span><br><span class="line">641</span><br><span class="line">642</span><br><span class="line">643</span><br><span class="line">644</span><br><span class="line">645</span><br><span class="line">646</span><br><span class="line">647</span><br><span class="line">648</span><br><span class="line">649</span><br><span class="line">650</span><br><span class="line">651</span><br><span class="line">652</span><br><span class="line">653</span><br><span class="line">654</span><br><span class="line">655</span><br><span class="line">656</span><br><span class="line">657</span><br><span class="line">658</span><br><span class="line">659</span><br><span class="line">660</span><br><span class="line">661</span><br><span class="line">662</span><br><span class="line">663</span><br><span class="line">664</span><br><span class="line">665</span><br><span class="line">666</span><br><span class="line">667</span><br><span class="line">668</span><br><span class="line">669</span><br></pre></td><td class="code"><pre><code class="hljs objectivec"><span class="hljs-meta">#import <span class="hljs-meta-string">"SecKeyWrapper.h"</span></span><br><span class="hljs-meta">#import <span class="hljs-meta-string"><CommonCrypto/CommonDigest.h></span></span><br><span class="hljs-meta">#import <span class="hljs-meta-string"><CommonCrypto/CommonCryptor.h></span></span><br><span class="hljs-meta">#import <span class="hljs-meta-string"><Security/SecKey.h></span></span><br><br><span class="hljs-class"><span class="hljs-keyword">@interface</span> <span class="hljs-title">SecKeyWrapper</span> () </span>{<br> <span class="hljs-built_in">NSData</span> *_publicTag;<br> <span class="hljs-built_in">NSData</span> *_privateTag;<br>}<br><br><span class="hljs-keyword">@end</span><br><br><span class="hljs-class"><span class="hljs-keyword">@implementation</span> <span class="hljs-title">SecKeyWrapper</span></span><br><br><span class="hljs-keyword">static</span> SecKeyWrapper *instance = <span class="hljs-literal">nil</span>;<br><br><br>+ (<span class="hljs-keyword">instancetype</span>)shareInstance {<br> <span class="hljs-keyword">static</span> <span class="hljs-built_in">dispatch_once_t</span> onceToken;<br> <span class="hljs-built_in">dispatch_once</span>(&onceToken, ^{<br> instance = [[<span class="hljs-keyword">super</span> allocWithZone:<span class="hljs-literal">NULL</span>] init];<br> });<br> <span class="hljs-keyword">return</span> instance;<br>}<br><br>- (<span class="hljs-keyword">instancetype</span>)init {<br> <span class="hljs-keyword">self</span> = [<span class="hljs-keyword">super</span> init];<br> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">self</span>) {<br> <span class="hljs-comment">// 单例的内部逻辑</span><br> <span class="hljs-comment">// 初始化tag标记,此字符串长度固定,内容可更改</span><br> _privateTag = [<span class="hljs-string">@"com.ghtest.rsasecprivatekey"</span> dataUsingEncoding:<span class="hljs-built_in">NSUTF8StringEncoding</span>];<br> _publicTag = [<span class="hljs-string">@"com.ghtest.rsasecpublickey"</span> dataUsingEncoding:<span class="hljs-built_in">NSUTF8StringEncoding</span>];<br> <br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">self</span>;<br>}<br><br>+ (<span class="hljs-keyword">instancetype</span>)allocWithZone:(<span class="hljs-keyword">struct</span> _NSZone *)zone {<br> <span class="hljs-keyword">return</span> [SecKeyWrapper shareInstance];<br>}<br><br>- (<span class="hljs-keyword">id</span>)copyWithZone:(<span class="hljs-built_in">NSZone</span> *)zone {<br> <span class="hljs-keyword">return</span> [SecKeyWrapper shareInstance];<br>}<br><br>- (<span class="hljs-keyword">id</span>)mutableCopyWithZone:(<span class="hljs-built_in">NSZone</span> *)zone {<br> <span class="hljs-keyword">return</span> [SecKeyWrapper shareInstance];<br>}<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 生成秘钥</span><br><span class="hljs-comment"> */</span><br>- (<span class="hljs-built_in">BOOL</span>)generateKeyPair:(<span class="hljs-built_in">NSUInteger</span>)keySize publicKey:(SecKeyRef _Nullable *_Nonnull)publicKeyRef privateKey:(SecKeyRef _Nullable *_Nonnull)privateKeyRef {<br> <br> <span class="hljs-keyword">if</span> (keySize == <span class="hljs-number">512</span> || keySize == <span class="hljs-number">1024</span> || keySize == <span class="hljs-number">2048</span>) {<br> <span class="hljs-comment">// 首先删除旧的秘钥</span><br> OSStatus sanityCheck = noErr;<br> <span class="hljs-built_in">NSMutableDictionary</span> *queryPublicKey = [[<span class="hljs-built_in">NSMutableDictionary</span> alloc] init];<br> <span class="hljs-built_in">NSMutableDictionary</span> *queryPrivateKey = [[<span class="hljs-built_in">NSMutableDictionary</span> alloc] init];<br> <span class="hljs-comment">// 设置公钥队列</span><br> [queryPublicKey setObject:(<span class="hljs-keyword">id</span>)kSecClassKey forKey:(<span class="hljs-keyword">id</span>)kSecClass];<br> [queryPublicKey setObject:_publicTag forKey:(<span class="hljs-keyword">id</span>)kSecAttrApplicationTag];<br> [queryPublicKey setObject:(<span class="hljs-keyword">id</span>)kSecAttrKeyTypeRSA forKey:(<span class="hljs-keyword">id</span>)kSecAttrKeyType];<br> <span class="hljs-comment">// 设置私钥队列</span><br> [queryPrivateKey setObject:(<span class="hljs-keyword">id</span>)kSecClassKey forKey:(<span class="hljs-keyword">id</span>)kSecClass];<br> [queryPrivateKey setObject:_privateTag forKey:(<span class="hljs-keyword">id</span>)kSecAttrApplicationTag];<br> [queryPrivateKey setObject:(<span class="hljs-keyword">id</span>)kSecAttrKeyTypeRSA forKey:(<span class="hljs-keyword">id</span>)kSecAttrKeyType];<br> <br> <span class="hljs-comment">// 删除私钥</span><br> sanityCheck = SecItemDelete((<span class="hljs-built_in">CFDictionaryRef</span>)queryPrivateKey);<br> <span class="hljs-keyword">if</span> (sanityCheck == noErr || sanityCheck == errSecItemNotFound) {<br> <br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"Error removing private key, OSStatus == %d."</span>, sanityCheck);<br> }<br> <span class="hljs-comment">// 删除公钥</span><br> sanityCheck = SecItemDelete((<span class="hljs-built_in">CFDictionaryRef</span>)queryPublicKey);<br> <span class="hljs-keyword">if</span> (sanityCheck == noErr || sanityCheck == errSecItemNotFound) {<br> <br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"Error removing public key, OSStatus == %d."</span>, sanityCheck);<br> }<br> <br> <span class="hljs-comment">// Container dictionaries.</span><br> <span class="hljs-built_in">NSMutableDictionary</span> *keyPairAttr = [[<span class="hljs-built_in">NSMutableDictionary</span> alloc] init];<br> <span class="hljs-built_in">NSMutableDictionary</span> *publicKeyAttr = [[<span class="hljs-built_in">NSMutableDictionary</span> alloc] init];<br> <span class="hljs-built_in">NSMutableDictionary</span> *privateKeyAttr = [[<span class="hljs-built_in">NSMutableDictionary</span> alloc] init];<br> <span class="hljs-comment">// Set top level dictionary for the keypair.</span><br> [keyPairAttr setObject:(<span class="hljs-keyword">id</span>)kSecAttrKeyTypeRSA forKey:(<span class="hljs-keyword">id</span>)kSecAttrKeyType];<br> [keyPairAttr setObject:[<span class="hljs-built_in">NSNumber</span> numberWithUnsignedInteger:keySize] forKey:(<span class="hljs-keyword">id</span>)kSecAttrKeySizeInBits];<br> <span class="hljs-comment">// 公钥字典,其他参数SecKey.h</span><br> [publicKeyAttr setObject:[<span class="hljs-built_in">NSNumber</span> numberWithBool:<span class="hljs-literal">YES</span>] forKey:(<span class="hljs-keyword">id</span>)kSecAttrIsPermanent];<br> [publicKeyAttr setObject:_publicTag forKey:(<span class="hljs-keyword">id</span>)kSecAttrApplicationTag];<br> <span class="hljs-comment">// 私钥字典,其他参数SecKey.h</span><br> [privateKeyAttr setObject:[<span class="hljs-built_in">NSNumber</span> numberWithBool:<span class="hljs-literal">YES</span>] forKey:(<span class="hljs-keyword">id</span>)kSecAttrIsPermanent];<br> [privateKeyAttr setObject:_privateTag forKey:(<span class="hljs-keyword">id</span>)kSecAttrApplicationTag];<br> <span class="hljs-comment">// Set attributes to top level dictionary.</span><br> [keyPairAttr setObject:publicKeyAttr forKey:(<span class="hljs-keyword">id</span>)kSecPublicKeyAttrs];<br> [keyPairAttr setObject:privateKeyAttr forKey:(<span class="hljs-keyword">id</span>)kSecPrivateKeyAttrs];<br> <br> <span class="hljs-comment">// 同步方法生成秘钥</span><br> OSStatus status = noErr;<br> status = SecKeyGeneratePair((<span class="hljs-built_in">CFDictionaryRef</span>)keyPairAttr, publicKeyRef, privateKeyRef);<br> <span class="hljs-keyword">if</span> (status == noErr && publicKeyRef != <span class="hljs-literal">NULL</span> && privateKeyRef != <span class="hljs-literal">NULL</span>) {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">YES</span>;<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"Something really bad went wrong with generating the key pair."</span>);<br> }<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">NO</span>;<br>}<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 公钥加密</span><br><span class="hljs-comment"> */</span><br>- (<span class="hljs-built_in">NSString</span> *)secKeyEncryptWithPublicKey:(SecKeyRef)publicKey plainString:(<span class="hljs-built_in">NSString</span> *)plainString {<br> <span class="hljs-comment">// 原数据</span><br> <span class="hljs-built_in">NSData</span> *plainData = [plainString dataUsingEncoding:<span class="hljs-built_in">NSUTF8StringEncoding</span>];<br> <span class="hljs-built_in">NSMutableData</span> *encryptData = [<span class="hljs-built_in">NSMutableData</span> data];<br> <span class="hljs-comment">// 循环分段加密,每次最多加密公钥长度,其中还需要kSecPaddingPKCS1填充,-11位</span><br> size_t cipherBufferSize = SecKeyGetBlockSize(publicKey);<br> <span class="hljs-built_in">NSUInteger</span> totalSize = plainData.length;<br> <span class="hljs-comment">// 分段数量</span><br> <span class="hljs-built_in">NSUInteger</span> blockSize = cipherBufferSize - <span class="hljs-number">11</span>;<br> <span class="hljs-keyword">double</span> blockCount = ceil(totalSize * <span class="hljs-number">1.</span>f / blockSize);<br> <span class="hljs-keyword">for</span> (<span class="hljs-built_in">NSInteger</span> i = <span class="hljs-number">0</span>; i < blockCount; i++) {<br> <span class="hljs-comment">// 取出当前分段数据</span><br> <span class="hljs-built_in">NSData</span> *blockData;<br> <span class="hljs-keyword">if</span> (i < (blockCount - <span class="hljs-number">1</span>)) {<br> blockData = [plainData subdataWithRange:<span class="hljs-built_in">NSMakeRange</span>(i * blockSize, blockSize)];<br> } <span class="hljs-keyword">else</span> {<br> blockData = [plainData subdataWithRange:<span class="hljs-built_in">NSMakeRange</span>(i * blockSize, totalSize - i * blockSize)];<br> }<br> <span class="hljs-comment">// 申请缓冲区内存,使用公钥长度申请</span><br> uint8_t *cipherBuffer = malloc(cipherBufferSize * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)cipherBuffer, <span class="hljs-number">0x0</span>, cipherBufferSize);<br> <span class="hljs-comment">// 加密</span><br> OSStatus sanityCheck = noErr;<br> sanityCheck = SecKeyEncrypt(publicKey, kSecPaddingPKCS1, (<span class="hljs-keyword">const</span> uint8_t *)[blockData bytes], [blockData length], cipherBuffer, &cipherBufferSize);<br> <span class="hljs-keyword">if</span> (sanityCheck == noErr) {<br> <span class="hljs-comment">// Build up cipher text blob.</span><br> <span class="hljs-built_in">NSData</span> *cipher = [<span class="hljs-built_in">NSData</span> dataWithBytes:(<span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *)cipherBuffer length:(<span class="hljs-built_in">NSUInteger</span>)cipherBufferSize];<br> [encryptData appendData:cipher];<br> <span class="hljs-keyword">if</span> (cipherBuffer) {<br> free(cipherBuffer);<br> }<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-comment">// 加密失败</span><br> <span class="hljs-keyword">if</span> (cipherBuffer) {<br> free(cipherBuffer);<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>;<br> }<br> }<br> <span class="hljs-comment">// 转base64</span><br> <span class="hljs-built_in">NSString</span> *encryptString = [encryptData base64EncodedStringWithOptions:<span class="hljs-number">0</span>];<br> <span class="hljs-keyword">return</span> encryptString;<br>}<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 私钥解密</span><br><span class="hljs-comment"> */</span><br>- (<span class="hljs-built_in">NSString</span> *)secKeyDecryptWithPrivateKey:(SecKeyRef)privateKey encryptString:(<span class="hljs-built_in">NSString</span> *)encryptString {<br> <span class="hljs-comment">// 原数据</span><br> <span class="hljs-built_in">NSData</span> *encryptData = [[<span class="hljs-built_in">NSData</span> alloc] initWithBase64EncodedString:encryptString options:<span class="hljs-built_in">NSDataBase64DecodingIgnoreUnknownCharacters</span>];<br> <span class="hljs-built_in">NSMutableData</span> *outputPlainData = [<span class="hljs-built_in">NSMutableData</span> data];<br> <span class="hljs-comment">// 循环分段解密,每次最多解密私钥长度</span><br> size_t cipherBufferSize = SecKeyGetBlockSize(privateKey);<br> <span class="hljs-built_in">NSUInteger</span> totalSize = encryptData.length;<br> <span class="hljs-comment">// 分段数量</span><br> <span class="hljs-built_in">NSUInteger</span> blockSize = cipherBufferSize;<br> <span class="hljs-keyword">double</span> blockCount = ceil(totalSize * <span class="hljs-number">1.</span>f / cipherBufferSize);<br> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < blockCount; i++) {<br> <span class="hljs-comment">// 取出当前分段数据</span><br> <span class="hljs-built_in">NSData</span> *blockData;<br> <span class="hljs-keyword">if</span> (i < (blockCount - <span class="hljs-number">1</span>)) {<br> blockData = [encryptData subdataWithRange:<span class="hljs-built_in">NSMakeRange</span>(i * blockSize, blockSize)];<br> } <span class="hljs-keyword">else</span> {<br> blockData = [encryptData subdataWithRange:<span class="hljs-built_in">NSMakeRange</span>(i * blockSize, totalSize - i * blockSize)];<br> }<br> <span class="hljs-comment">// 申请当前分段加密占用内存</span><br> uint8_t *keyBuffer = malloc(cipherBufferSize * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)keyBuffer, <span class="hljs-number">0x0</span>, cipherBufferSize);<br> <span class="hljs-comment">// 解密</span><br> OSStatus status = noErr;<br> status = SecKeyDecrypt(privateKey, kSecPaddingPKCS1, (<span class="hljs-keyword">const</span> uint8_t *)[blockData bytes], [blockData length], keyBuffer, &cipherBufferSize);<br> <span class="hljs-keyword">if</span> (status == noErr) {<br> <span class="hljs-built_in">NSData</span> *key = [<span class="hljs-built_in">NSData</span> dataWithBytes:(<span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *)keyBuffer length:(<span class="hljs-built_in">NSUInteger</span>)cipherBufferSize];<br> [outputPlainData appendData:key];<br> <span class="hljs-keyword">if</span> (keyBuffer) {<br> free(keyBuffer);<br> }<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">if</span> (keyBuffer) {<br> free(keyBuffer);<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>;<br> }<br> }<br><br> <span class="hljs-built_in">NSString</span> *outputPlainString = [[<span class="hljs-built_in">NSString</span> alloc] initWithData:outputPlainData encoding:<span class="hljs-built_in">NSUTF8StringEncoding</span>];<br> <span class="hljs-keyword">return</span> outputPlainString;<br>}<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 私钥签名</span><br><span class="hljs-comment"> */</span><br>- (<span class="hljs-built_in">NSString</span> *)signWithPrivateSecKey:(SecKeyRef)privateKey secPadding:(SecPadding)secPadding plainString:(<span class="hljs-built_in">NSString</span> *)plainString {<br><span class="hljs-meta">#<span class="hljs-meta-keyword">if</span> __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_10_0</span><br> <span class="hljs-comment">// 原数据</span><br> <span class="hljs-built_in">NSData</span> *plainData = [plainString dataUsingEncoding:<span class="hljs-built_in">NSUTF8StringEncoding</span>];<br> <span class="hljs-comment">// 哈希值算法,md5、sha1、sha224、sha256、sha384、sha512</span><br> <span class="hljs-built_in">NSData</span> *hashData = <span class="hljs-literal">nil</span>;<br> <span class="hljs-built_in">NSInteger</span> digest_length = <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">switch</span> (secPadding) {<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1MD5:<br> {<br> digest_length = CC_MD5_DIGEST_LENGTH;<br> <span class="hljs-comment">// Malloc a buffer to hold hash.</span><br> uint8_t *hashBytes = malloc(CC_MD5_DIGEST_LENGTH * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)hashBytes, <span class="hljs-number">0x0</span>, CC_MD5_DIGEST_LENGTH);<br> <span class="hljs-comment">// Initialize the context.</span><br> CC_MD5_CTX ctx;<br> CC_MD5_Init(&ctx);<br> <span class="hljs-comment">// Perform the hash.</span><br> CC_MD5_Update(&ctx, (<span class="hljs-keyword">void</span> *)[plainData bytes], (CC_LONG)[plainData length]);<br> <span class="hljs-comment">// Finalize the output.</span><br> CC_MD5_Final(hashBytes, &ctx);<br> <span class="hljs-comment">// Build up the SHAMD5 blob.</span><br> hashData = [<span class="hljs-built_in">NSData</span> dataWithBytes:(<span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *)hashBytes length:(<span class="hljs-built_in">NSUInteger</span>)CC_MD5_DIGEST_LENGTH];<br> <span class="hljs-keyword">if</span> (hashBytes) {<br> free(hashBytes);<br> }<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA1:<br> {<br> digest_length = CC_SHA1_DIGEST_LENGTH;<br> <span class="hljs-comment">// Malloc a buffer to hold hash.</span><br> uint8_t *hashBytes = malloc(CC_SHA1_DIGEST_LENGTH * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)hashBytes, <span class="hljs-number">0x0</span>, CC_SHA1_DIGEST_LENGTH);<br> <span class="hljs-comment">// Initialize the context.</span><br> CC_SHA1_CTX ctx;<br> CC_SHA1_Init(&ctx);<br> <span class="hljs-comment">// Perform the hash.</span><br> CC_SHA1_Update(&ctx, (<span class="hljs-keyword">void</span> *)[plainData bytes], (CC_LONG)[plainData length]);<br> <span class="hljs-comment">// Finalize the output.</span><br> CC_SHA1_Final(hashBytes, &ctx);<br> <span class="hljs-comment">// Build up the SHA1 blob.</span><br> hashData = [<span class="hljs-built_in">NSData</span> dataWithBytes:(<span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *)hashBytes length:(<span class="hljs-built_in">NSUInteger</span>)CC_SHA1_DIGEST_LENGTH];<br> <span class="hljs-keyword">if</span> (hashBytes) {<br> free(hashBytes);<br> }<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA224:<br> {<br> digest_length = CC_SHA224_DIGEST_LENGTH;<br> <span class="hljs-comment">// Malloc a buffer to hold hash.</span><br> uint8_t *hashBytes = malloc(CC_SHA224_DIGEST_LENGTH * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)hashBytes, <span class="hljs-number">0x0</span>, CC_SHA224_DIGEST_LENGTH);<br> <span class="hljs-comment">// Initialize the context.</span><br> CC_SHA256_CTX ctx;<br> CC_SHA224_Init(&ctx);<br> <span class="hljs-comment">// Perform the hash.</span><br> CC_SHA224_Update(&ctx, (<span class="hljs-keyword">void</span> *)[plainData bytes], (CC_LONG)[plainData length]);<br> <span class="hljs-comment">// Finalize the output.</span><br> CC_SHA224_Final(hashBytes, &ctx);<br> <span class="hljs-comment">// Build up the SHA224 blob.</span><br> hashData = [<span class="hljs-built_in">NSData</span> dataWithBytes:(<span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *)hashBytes length:(<span class="hljs-built_in">NSUInteger</span>)CC_SHA224_DIGEST_LENGTH];<br> <span class="hljs-keyword">if</span> (hashBytes) {<br> free(hashBytes);<br> }<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA256:<br> {<br> digest_length = CC_SHA256_DIGEST_LENGTH;<br> <span class="hljs-comment">// Malloc a buffer to hold hash.</span><br> uint8_t *hashBytes = malloc(CC_SHA256_DIGEST_LENGTH * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)hashBytes, <span class="hljs-number">0x0</span>, CC_SHA256_DIGEST_LENGTH);<br> <span class="hljs-comment">// Initialize the context.</span><br> CC_SHA256_CTX ctx;<br> CC_SHA256_Init(&ctx);<br> <span class="hljs-comment">// Perform the hash.</span><br> CC_SHA256_Update(&ctx, (<span class="hljs-keyword">void</span> *)[plainData bytes], (CC_LONG)[plainData length]);<br> <span class="hljs-comment">// Finalize the output.</span><br> CC_SHA256_Final(hashBytes, &ctx);<br> <span class="hljs-comment">// Build up the SHA256 blob.</span><br> hashData = [<span class="hljs-built_in">NSData</span> dataWithBytes:(<span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *)hashBytes length:(<span class="hljs-built_in">NSUInteger</span>)CC_SHA256_DIGEST_LENGTH];<br> <span class="hljs-keyword">if</span> (hashBytes) {<br> free(hashBytes);<br> }<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA384:<br> {<br> digest_length = CC_SHA384_DIGEST_LENGTH;<br> <span class="hljs-comment">// Malloc a buffer to hold hash.</span><br> uint8_t *hashBytes = malloc(CC_SHA384_DIGEST_LENGTH * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)hashBytes, <span class="hljs-number">0x0</span>, CC_SHA384_DIGEST_LENGTH);<br> <span class="hljs-comment">// Initialize the context.</span><br> CC_SHA512_CTX ctx;<br> CC_SHA384_Init(&ctx);<br> <span class="hljs-comment">// Perform the hash.</span><br> CC_SHA384_Update(&ctx, (<span class="hljs-keyword">void</span> *)[plainData bytes], (CC_LONG)[plainData length]);<br> <span class="hljs-comment">// Finalize the output.</span><br> CC_SHA384_Final(hashBytes, &ctx);<br> <span class="hljs-comment">// Build up the SHA384 blob.</span><br> hashData = [<span class="hljs-built_in">NSData</span> dataWithBytes:(<span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *)hashBytes length:(<span class="hljs-built_in">NSUInteger</span>)CC_SHA384_DIGEST_LENGTH];<br> <span class="hljs-keyword">if</span> (hashBytes) {<br> free(hashBytes);<br> }<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA512:<br> {<br> digest_length = CC_SHA512_DIGEST_LENGTH;<br> <span class="hljs-comment">// Malloc a buffer to hold hash.</span><br> uint8_t *hashBytes = malloc(CC_SHA512_DIGEST_LENGTH * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)hashBytes, <span class="hljs-number">0x0</span>, CC_SHA512_DIGEST_LENGTH);<br> <span class="hljs-comment">// Initialize the context.</span><br> CC_SHA512_CTX ctx;<br> CC_SHA512_Init(&ctx);<br> <span class="hljs-comment">// Perform the hash.</span><br> CC_SHA512_Update(&ctx, (<span class="hljs-keyword">void</span> *)[plainData bytes], (CC_LONG)[plainData length]);<br> <span class="hljs-comment">// Finalize the output.</span><br> CC_SHA512_Final(hashBytes, &ctx);<br> <span class="hljs-comment">// Build up the SHA512 blob.</span><br> hashData = [<span class="hljs-built_in">NSData</span> dataWithBytes:(<span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *)hashBytes length:(<span class="hljs-built_in">NSUInteger</span>)CC_SHA512_DIGEST_LENGTH];<br> <span class="hljs-keyword">if</span> (hashBytes) {<br> free(hashBytes);<br> }<br> }<br> <span class="hljs-keyword">break</span>;<br> <br> <span class="hljs-keyword">default</span>:<br> <span class="hljs-keyword">break</span>;<br> }<br> <span class="hljs-keyword">if</span> (hashData) {<br> size_t signedHashBytesSize = SecKeyGetBlockSize(privateKey);<br> <span class="hljs-comment">// Malloc a buffer to hold signature.</span><br> uint8_t *signedHashBytes = malloc(signedHashBytesSize * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)signedHashBytes, <span class="hljs-number">0x0</span>, signedHashBytesSize);<br> <span class="hljs-comment">// Sign the hash Data.</span><br> OSStatus sanityCheck = noErr;<br> sanityCheck = SecKeyRawSign(privateKey, secPadding, (<span class="hljs-keyword">const</span> uint8_t *)[hashData bytes], digest_length, (uint8_t *)signedHashBytes, &signedHashBytesSize);<br> <span class="hljs-keyword">if</span> (sanityCheck == noErr) {<br> <span class="hljs-comment">// Build up signed blob.</span><br> <span class="hljs-built_in">NSData</span> *signedHash = [<span class="hljs-built_in">NSData</span> dataWithBytes:(<span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *)signedHashBytes length:(<span class="hljs-built_in">NSUInteger</span>)signedHashBytesSize];<br> <span class="hljs-keyword">if</span> (signedHashBytes) {<br> free(signedHashBytes);<br> }<br> <span class="hljs-built_in">NSString</span> *signString = [signedHash base64EncodedStringWithOptions:<span class="hljs-number">0</span>];<br> <span class="hljs-keyword">return</span> signString;<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">if</span> (signedHashBytes) {<br> free(signedHashBytes);<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>;<br> }<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>;<br> }<br><span class="hljs-meta">#<span class="hljs-meta-keyword">else</span></span><br> <span class="hljs-comment">// iOS10以上系统可以使用新的方法</span><br> <span class="hljs-comment">// 原数据</span><br> <span class="hljs-built_in">NSData</span> *plainData = [plainString dataUsingEncoding:<span class="hljs-built_in">NSUTF8StringEncoding</span>];<br> SecKeyAlgorithm Algorithm = <span class="hljs-literal">nil</span>;<br> <span class="hljs-keyword">switch</span> (secPadding) {<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA1:<br> {<br> Algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA224:<br> {<br> Algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA256:<br> {<br> Algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA384:<br> {<br> Algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA512:<br> {<br> Algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512;<br> }<br> <span class="hljs-keyword">break</span>;<br> <br> <span class="hljs-keyword">default</span>:<br> <span class="hljs-keyword">break</span>;<br> }<br> <span class="hljs-keyword">if</span> (Algorithm) {<br> <span class="hljs-built_in">NSError</span> *error = <span class="hljs-literal">nil</span>;<br> <span class="hljs-built_in">CFErrorRef</span> ee = (__bridge <span class="hljs-built_in">CFErrorRef</span>)error;<br> <span class="hljs-built_in">CFDataRef</span> dataRef = SecKeyCreateSignature(privateKey, kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1, (<span class="hljs-built_in">CFDataRef</span>)plainData, &ee);<br> <span class="hljs-keyword">if</span> (error) {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>;<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-built_in">NSData</span> *signature = <span class="hljs-built_in">CFBridgingRelease</span>(dataRef);<br> <span class="hljs-built_in">NSString</span> *signString = [signature base64EncodedStringWithOptions:<span class="hljs-number">0</span>];<br> <span class="hljs-keyword">return</span> signString;<br> }<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>;<br> }<br><span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span><br>}<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 公钥验证签名</span><br><span class="hljs-comment"> */</span><br>- (<span class="hljs-built_in">BOOL</span>)verifyWithPublicSecKey:(SecKeyRef)publicKey secPadding:(SecPadding)secPadding plainString:(<span class="hljs-built_in">NSString</span> *)plainString signString:(<span class="hljs-built_in">NSString</span> *)signString {<br><span class="hljs-meta">#<span class="hljs-meta-keyword">if</span> __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_10_0</span><br> <span class="hljs-comment">// 原数据</span><br> <span class="hljs-built_in">NSData</span> *plainData = [plainString dataUsingEncoding:<span class="hljs-built_in">NSUTF8StringEncoding</span>];<br> <span class="hljs-comment">// 哈希值算法,md5、sha1、sha224、sha256、sha384、sha512</span><br> <span class="hljs-built_in">NSData</span> *hashData = <span class="hljs-literal">nil</span>;<br> <span class="hljs-built_in">NSInteger</span> digest_length = <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">switch</span> (secPadding) {<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1MD5:<br> {<br> digest_length = CC_MD5_DIGEST_LENGTH;<br> <span class="hljs-comment">// Malloc a buffer to hold hash.</span><br> uint8_t *hashBytes = malloc(CC_MD5_DIGEST_LENGTH * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)hashBytes, <span class="hljs-number">0x0</span>, CC_MD5_DIGEST_LENGTH);<br> <span class="hljs-comment">// Initialize the context.</span><br> CC_MD5_CTX ctx;<br> CC_MD5_Init(&ctx);<br> <span class="hljs-comment">// Perform the hash.</span><br> CC_MD5_Update(&ctx, (<span class="hljs-keyword">void</span> *)[plainData bytes], (CC_LONG)[plainData length]);<br> <span class="hljs-comment">// Finalize the output.</span><br> CC_MD5_Final(hashBytes, &ctx);<br> <span class="hljs-comment">// Build up the SHAMD5 blob.</span><br> hashData = [<span class="hljs-built_in">NSData</span> dataWithBytes:(<span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *)hashBytes length:(<span class="hljs-built_in">NSUInteger</span>)CC_MD5_DIGEST_LENGTH];<br> <span class="hljs-keyword">if</span> (hashBytes) {<br> free(hashBytes);<br> }<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA1:<br> {<br> digest_length = CC_SHA1_DIGEST_LENGTH;<br> <span class="hljs-comment">// Malloc a buffer to hold hash.</span><br> uint8_t *hashBytes = malloc(CC_SHA1_DIGEST_LENGTH * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)hashBytes, <span class="hljs-number">0x0</span>, CC_SHA1_DIGEST_LENGTH);<br> <span class="hljs-comment">// Initialize the context.</span><br> CC_SHA1_CTX ctx;<br> CC_SHA1_Init(&ctx);<br> <span class="hljs-comment">// Perform the hash.</span><br> CC_SHA1_Update(&ctx, (<span class="hljs-keyword">void</span> *)[plainData bytes], (CC_LONG)[plainData length]);<br> <span class="hljs-comment">// Finalize the output.</span><br> CC_SHA1_Final(hashBytes, &ctx);<br> <span class="hljs-comment">// Build up the SHA1 blob.</span><br> hashData = [<span class="hljs-built_in">NSData</span> dataWithBytes:(<span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *)hashBytes length:(<span class="hljs-built_in">NSUInteger</span>)CC_SHA1_DIGEST_LENGTH];<br> <span class="hljs-keyword">if</span> (hashBytes) {<br> free(hashBytes);<br> }<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA224:<br> {<br> digest_length = CC_SHA224_DIGEST_LENGTH;<br> <span class="hljs-comment">// Malloc a buffer to hold hash.</span><br> uint8_t *hashBytes = malloc(CC_SHA224_DIGEST_LENGTH * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)hashBytes, <span class="hljs-number">0x0</span>, CC_SHA224_DIGEST_LENGTH);<br> <span class="hljs-comment">// Initialize the context.</span><br> CC_SHA256_CTX ctx;<br> CC_SHA224_Init(&ctx);<br> <span class="hljs-comment">// Perform the hash.</span><br> CC_SHA224_Update(&ctx, (<span class="hljs-keyword">void</span> *)[plainData bytes], (CC_LONG)[plainData length]);<br> <span class="hljs-comment">// Finalize the output.</span><br> CC_SHA224_Final(hashBytes, &ctx);<br> <span class="hljs-comment">// Build up the SHA224 blob.</span><br> hashData = [<span class="hljs-built_in">NSData</span> dataWithBytes:(<span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *)hashBytes length:(<span class="hljs-built_in">NSUInteger</span>)CC_SHA224_DIGEST_LENGTH];<br> <span class="hljs-keyword">if</span> (hashBytes) {<br> free(hashBytes);<br> }<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA256:<br> {<br> digest_length = CC_SHA256_DIGEST_LENGTH;<br> <span class="hljs-comment">// Malloc a buffer to hold hash.</span><br> uint8_t *hashBytes = malloc(CC_SHA256_DIGEST_LENGTH * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)hashBytes, <span class="hljs-number">0x0</span>, CC_SHA256_DIGEST_LENGTH);<br> <span class="hljs-comment">// Initialize the context.</span><br> CC_SHA256_CTX ctx;<br> CC_SHA256_Init(&ctx);<br> <span class="hljs-comment">// Perform the hash.</span><br> CC_SHA256_Update(&ctx, (<span class="hljs-keyword">void</span> *)[plainData bytes], (CC_LONG)[plainData length]);<br> <span class="hljs-comment">// Finalize the output.</span><br> CC_SHA256_Final(hashBytes, &ctx);<br> <span class="hljs-comment">// Build up the SHA256 blob.</span><br> hashData = [<span class="hljs-built_in">NSData</span> dataWithBytes:(<span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *)hashBytes length:(<span class="hljs-built_in">NSUInteger</span>)CC_SHA256_DIGEST_LENGTH];<br> <span class="hljs-keyword">if</span> (hashBytes) {<br> free(hashBytes);<br> }<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA384:<br> {<br> digest_length = CC_SHA384_DIGEST_LENGTH;<br> <span class="hljs-comment">// Malloc a buffer to hold hash.</span><br> uint8_t *hashBytes = malloc(CC_SHA384_DIGEST_LENGTH * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)hashBytes, <span class="hljs-number">0x0</span>, CC_SHA384_DIGEST_LENGTH);<br> <span class="hljs-comment">// Initialize the context.</span><br> CC_SHA512_CTX ctx;<br> CC_SHA384_Init(&ctx);<br> <span class="hljs-comment">// Perform the hash.</span><br> CC_SHA384_Update(&ctx, (<span class="hljs-keyword">void</span> *)[plainData bytes], (CC_LONG)[plainData length]);<br> <span class="hljs-comment">// Finalize the output.</span><br> CC_SHA384_Final(hashBytes, &ctx);<br> <span class="hljs-comment">// Build up the SHA384 blob.</span><br> hashData = [<span class="hljs-built_in">NSData</span> dataWithBytes:(<span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *)hashBytes length:(<span class="hljs-built_in">NSUInteger</span>)CC_SHA384_DIGEST_LENGTH];<br> <span class="hljs-keyword">if</span> (hashBytes) {<br> free(hashBytes);<br> }<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA512:<br> {<br> digest_length = CC_SHA512_DIGEST_LENGTH;<br> <span class="hljs-comment">// Malloc a buffer to hold hash.</span><br> uint8_t *hashBytes = malloc(CC_SHA512_DIGEST_LENGTH * <span class="hljs-keyword">sizeof</span>(uint8_t));<br> memset((<span class="hljs-keyword">void</span> *)hashBytes, <span class="hljs-number">0x0</span>, CC_SHA512_DIGEST_LENGTH);<br> <span class="hljs-comment">// Initialize the context.</span><br> CC_SHA512_CTX ctx;<br> CC_SHA512_Init(&ctx);<br> <span class="hljs-comment">// Perform the hash.</span><br> CC_SHA512_Update(&ctx, (<span class="hljs-keyword">void</span> *)[plainData bytes], (CC_LONG)[plainData length]);<br> <span class="hljs-comment">// Finalize the output.</span><br> CC_SHA512_Final(hashBytes, &ctx);<br> <span class="hljs-comment">// Build up the SHA512 blob.</span><br> hashData = [<span class="hljs-built_in">NSData</span> dataWithBytes:(<span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *)hashBytes length:(<span class="hljs-built_in">NSUInteger</span>)CC_SHA512_DIGEST_LENGTH];<br> <span class="hljs-keyword">if</span> (hashBytes) {<br> free(hashBytes);<br> }<br> }<br> <span class="hljs-keyword">break</span>;<br> <br> <span class="hljs-keyword">default</span>:<br> <span class="hljs-keyword">break</span>;<br> }<br> <span class="hljs-keyword">if</span> (hashData) {<br> <span class="hljs-comment">// 签名数据</span><br> <span class="hljs-built_in">NSData</span> *signData = [[<span class="hljs-built_in">NSData</span> alloc] initWithBase64EncodedString:signString options:<span class="hljs-built_in">NSDataBase64DecodingIgnoreUnknownCharacters</span>];<br> <span class="hljs-comment">// Get the size of the assymetric block.</span><br> size_t signedHashBytesSize = SecKeyGetBlockSize(publicKey);<br> OSStatus sanityCheck = noErr;<br> sanityCheck = SecKeyRawVerify(publicKey, secPadding, (<span class="hljs-keyword">const</span> uint8_t *)[hashData bytes], digest_length, (<span class="hljs-keyword">const</span> uint8_t *)[signData bytes], signedHashBytesSize);<br> <span class="hljs-keyword">if</span> (sanityCheck == noErr) {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">YES</span>;<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">NO</span>;<br> }<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">NO</span>;<br> }<br><span class="hljs-meta">#<span class="hljs-meta-keyword">else</span></span><br> <span class="hljs-comment">// iOS10以上系统可以使用新的方法</span><br> <span class="hljs-comment">// 原数据</span><br> <span class="hljs-built_in">NSData</span> *plainData = [plainString dataUsingEncoding:<span class="hljs-built_in">NSUTF8StringEncoding</span>];<br> <span class="hljs-comment">// 签名数据</span><br> <span class="hljs-built_in">NSData</span> *signData = [[<span class="hljs-built_in">NSData</span> alloc] initWithBase64EncodedString:signString options:<span class="hljs-built_in">NSDataBase64DecodingIgnoreUnknownCharacters</span>];<br> SecKeyAlgorithm Algorithm = <span class="hljs-literal">nil</span>;<br> <span class="hljs-keyword">switch</span> (secPadding) {<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA1:<br> {<br> Algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA224:<br> {<br> Algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA256:<br> {<br> Algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA384:<br> {<br> Algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384;<br> }<br> <span class="hljs-keyword">break</span>;<br> <span class="hljs-keyword">case</span> kSecPaddingPKCS1SHA512:<br> {<br> Algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512;<br> }<br> <span class="hljs-keyword">break</span>;<br> <br> <span class="hljs-keyword">default</span>:<br> <span class="hljs-keyword">break</span>;<br> }<br> <span class="hljs-keyword">if</span> (Algorithm) {<br> <span class="hljs-built_in">NSError</span> *error = <span class="hljs-literal">nil</span>;<br> <span class="hljs-built_in">CFErrorRef</span> ee = (__bridge <span class="hljs-built_in">CFErrorRef</span>)error;<br> Boolean boolen = SecKeyVerifySignature(publicKey, Algorithm, (<span class="hljs-built_in">CFDataRef</span>)plainData, (<span class="hljs-built_in">CFDataRef</span>)signData, &ee);<br> <span class="hljs-keyword">if</span> (error) {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">NO</span>;<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">if</span> (boolen == <span class="hljs-literal">TRUE</span>) {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">YES</span>;<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">NO</span>;<br> }<br> }<br> } <span class="hljs-keyword">else</span> {<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">NO</span>;<br> }<br><span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span><br>}<br><br><span class="hljs-meta">#<span class="hljs-meta-keyword">if</span> __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0</span><br><br><span class="hljs-comment">// SecKeyRef转base64</span><br>- (<span class="hljs-built_in">NSString</span> *)base64StringFromSecKey:(SecKeyRef)secKey {<br> <span class="hljs-built_in">NSData</span> *keyData = (<span class="hljs-built_in">NSData</span> *)<span class="hljs-built_in">CFBridgingRelease</span>(SecKeyCopyExternalRepresentation(secKey, <span class="hljs-literal">NULL</span>));<br> <span class="hljs-built_in">NSString</span> *base64 = [keyData base64EncodedStringWithOptions:<span class="hljs-number">0</span>];<br> <span class="hljs-keyword">return</span> base64;<br>}<br><br><span class="hljs-comment">// base64转SecKeyRef</span><br>- (SecKeyRef)publicSecKeyFromBase64String:(<span class="hljs-built_in">NSString</span> *)keyString {<br> <span class="hljs-built_in">NSData</span> *keyData = [[<span class="hljs-built_in">NSData</span> alloc] initWithBase64EncodedString:keyString options:<span class="hljs-built_in">NSDataBase64DecodingIgnoreUnknownCharacters</span>];<br> <br> <span class="hljs-built_in">NSMutableDictionary</span> *options = [<span class="hljs-built_in">NSMutableDictionary</span> dictionary];<br> options[(__bridge <span class="hljs-keyword">id</span>)kSecAttrKeyType] = (__bridge <span class="hljs-keyword">id</span>) kSecAttrKeyTypeRSA;<br> options[(__bridge <span class="hljs-keyword">id</span>)kSecAttrKeyClass] = (__bridge <span class="hljs-keyword">id</span>) kSecAttrKeyClassPublic;<br> <br> <span class="hljs-built_in">NSError</span> *error = <span class="hljs-literal">nil</span>;<br> <span class="hljs-built_in">CFErrorRef</span> ee = (__bridge <span class="hljs-built_in">CFErrorRef</span>)error;<br> SecKeyRef ref = SecKeyCreateWithData((__bridge <span class="hljs-built_in">CFDataRef</span>)keyData, (__bridge <span class="hljs-built_in">CFDictionaryRef</span>)options, &ee);<br> <span class="hljs-keyword">if</span> (error) {<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"%@"</span>, error.description);<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>;<br> }<br> <span class="hljs-keyword">return</span> ref;<br>}<br><br>- (SecKeyRef)privateSecKeyFromBase64String:(<span class="hljs-built_in">NSString</span> *)keyString {<br> <span class="hljs-built_in">NSData</span> *keyData = [[<span class="hljs-built_in">NSData</span> alloc] initWithBase64EncodedString:keyString options:<span class="hljs-built_in">NSDataBase64DecodingIgnoreUnknownCharacters</span>];<br> <br> <span class="hljs-built_in">NSMutableDictionary</span> *options = [<span class="hljs-built_in">NSMutableDictionary</span> dictionary];<br> options[(__bridge <span class="hljs-keyword">id</span>)kSecAttrKeyType] = (__bridge <span class="hljs-keyword">id</span>) kSecAttrKeyTypeRSA;<br> options[(__bridge <span class="hljs-keyword">id</span>)kSecAttrKeyClass] = (__bridge <span class="hljs-keyword">id</span>) kSecAttrKeyClassPrivate;<br> <br> <span class="hljs-built_in">NSError</span> *error = <span class="hljs-literal">nil</span>;<br> <span class="hljs-built_in">CFErrorRef</span> ee = (__bridge <span class="hljs-built_in">CFErrorRef</span>)error;<br> SecKeyRef ref = SecKeyCreateWithData((__bridge <span class="hljs-built_in">CFDataRef</span>)keyData, (__bridge <span class="hljs-built_in">CFDictionaryRef</span>)options, &ee);<br> <span class="hljs-keyword">if</span> (error) {<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"%@"</span>, error.description);<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>;<br> }<br> <span class="hljs-keyword">return</span> ref;<br>}<br><br><span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span><br><br><span class="hljs-keyword">@end</span><br></code></pre></td></tr></table></figure><p>调用示例:</p><figure class="highlight objectivec"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><code class="hljs objectivec"><span class="hljs-meta">#import <span class="hljs-meta-string">"ViewController.h"</span></span><br><span class="hljs-meta">#import <span class="hljs-meta-string">"SecKeyWrapper.h"</span></span><br><br><span class="hljs-class"><span class="hljs-keyword">@interface</span> <span class="hljs-title">ViewController</span> () </span>{<br> SecKeyRef _publicKeyRef;<br> SecKeyRef _privateKeyRef;<br>}<br><span class="hljs-keyword">@end</span><br><br><span class="hljs-class"><span class="hljs-keyword">@implementation</span> <span class="hljs-title">ViewController</span></span><br><br>- (<span class="hljs-keyword">void</span>)viewDidLoad {<br> [<span class="hljs-keyword">super</span> viewDidLoad];<br> <span class="hljs-comment">// Do any additional setup after loading the view.</span><br> <br> _publicKeyRef = <span class="hljs-literal">NULL</span>;<br> _privateKeyRef = <span class="hljs-literal">NULL</span>;<br> SecKeyWrapper *secKeyWrapper = [SecKeyWrapper shareInstance];<br> [secKeyWrapper generateKeyPair:<span class="hljs-number">1024</span> publicKey:&_publicKeyRef privateKey:&_privateKeyRef];<br><br> <span class="hljs-built_in">NSString</span> *publicKeyBase64 = [secKeyWrapper base64StringFromSecKey:_publicKeyRef];<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"公钥:%@"</span>, publicKeyBase64);<br> <span class="hljs-built_in">NSString</span> *privateKeyBase64 = [secKeyWrapper base64StringFromSecKey:_privateKeyRef];<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"私钥:%@"</span>, privateKeyBase64);<br><br> <span class="hljs-built_in">NSString</span> *plainString = <span class="hljs-string">@"123qweQWE测试@#%&*"</span>;<br><br> <span class="hljs-built_in">NSString</span> *encryptedString = [secKeyWrapper secKeyEncryptWithPublicKey:_publicKeyRef plainString:plainString];<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"%@"</span>, [<span class="hljs-built_in">NSString</span> stringWithFormat:<span class="hljs-string">@"公钥加密:%@"</span>, encryptedString]);<br><br> <span class="hljs-built_in">NSString</span> *outputPlainString = [secKeyWrapper secKeyDecryptWithPrivateKey:_privateKeyRef encryptString:encryptedString];<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"%@"</span>, [<span class="hljs-built_in">NSString</span> stringWithFormat:<span class="hljs-string">@"私钥解密:%@"</span>, outputPlainString]);<br><br> <span class="hljs-built_in">NSString</span> *signString = [secKeyWrapper signWithPrivateSecKey:_privateKeyRef secPadding:kSecPaddingPKCS1SHA1 plainString:plainString];<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"%@"</span>, [<span class="hljs-built_in">NSString</span> stringWithFormat:<span class="hljs-string">@"私钥签名:%@"</span>, signString]);<br><br> <span class="hljs-built_in">BOOL</span> verify = [secKeyWrapper verifyWithPublicSecKey:_publicKeyRef secPadding:kSecPaddingPKCS1SHA1 plainString:plainString signString:signString];<br> <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"%@"</span>, [<span class="hljs-built_in">NSString</span> stringWithFormat:<span class="hljs-string">@"验证 %@"</span>, verify ? <span class="hljs-string">@"通过"</span> : <span class="hljs-string">@"不通过"</span>]);<br>}<br><br><span class="hljs-keyword">@end</span><br></code></pre></td></tr></table></figure><h5 id="3、一些概念"><a href="#3、一些概念" class="headerlink" title="3、一些概念"></a>3、一些概念</h5><ol><li>公钥加密,私钥解密</li></ol><blockquote><p>对于二进制数据,加密时为了确定内容实际长度,所以在末尾需要用约定好的字符进行标记结尾,防止被内存中的垃圾数据等影响,这就是<code>padding</code>,<code>PKCS1</code>格式秘钥建议使用的<code>padding</code>为11字节</p></blockquote><blockquote><p>以1024位秘钥为例,公钥加密时支持最大字节数:证书位数/8-11=117,解密时支持最大字节数:证书位数/8=128</p></blockquote><ol start="2"><li>私钥签名,公钥验签</li></ol><blockquote><p>私钥签名,公钥验签是为了对数据进行验证,确保数据没有被篡改</p></blockquote><blockquote><p>需要使用哈希值算法获取原数据的哈希值,哈希值特点是唯一性,一旦原数据发生变化,哈希值也会变化,再使用私钥对哈希值进行摘要签名,通过公钥验证后即可确保数据的保密性</p></blockquote><h5 id="4、遗留的问题"><a href="#4、遗留的问题" class="headerlink" title="4、遗留的问题"></a>4、遗留的问题</h5><p>在使用<code>Security</code>生成秘钥的过程中,发现一个问题:</p><blockquote><p>使用<code>Security</code>生成公钥私钥,其中私钥转成<code>base64</code>字符串后,可以使用<code>Openssl</code>的方法读取私钥,并使用<code>Openssl</code>的方法进行其他操作,但是公钥长度格式不对,无法使用<code>Openssl</code>的方法读取使用,如果要发送公钥给第三方,只能用<code>Openssl</code>的方法读取到公钥并发送,正常使用过程中,<code>Security</code>的公钥只能给<code>Security</code>自己的方法使用,对加密解密的功能没有影响,暂时无法找到合理的解释。</p></blockquote><p>另外,<code>Security</code>的部分方法在<code>iOS 10.0</code>后的系统才会生效,也没有找到以前以前系统中提供其他类似的方法,据网上资料了解,<code>Openssl</code>生成秘钥的方法有失败的可能,但是实际测试没有出现过,可能是测试数量不够多</p>]]></content>
<categories>
<category>iOS</category>
</categories>
<tags>
<tag>iOS</tag>
<tag>RSA</tag>
</tags>
</entry>
<entry>
<title>Flex布局简析</title>
<link href="/2019/08/10/Flex%E5%B8%83%E5%B1%80%E7%AE%80%E6%9E%90/"/>
<url>/2019/08/10/Flex%E5%B8%83%E5%B1%80%E7%AE%80%E6%9E%90/</url>
<content type="html"><![CDATA[<p>本文摘自<a href="http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html">阮一峰的网络日志Flex 布局教程:语法篇</a></p><h3 id="一、定义"><a href="#一、定义" class="headerlink" title="一、定义"></a>一、定义</h3><blockquote><p><code>Flexible Box</code>意为“弹性布局”,简写<code>flex</code>,之前已经了解过流动模型、浮动模型、层模型的布局,<code>flex</code>布局能够为盒状模型提供最大的灵活性。</p></blockquote><blockquote><p>任何一个容器都可以指定为<code>flex</code>布局,行内元素也可以,但需要注意个浏览器的支持情况,目前<code>Chrome 21+</code>,<code>Firefox 22+</code>,<code>IE 10+</code>,<code>Safari 6.1+</code>以上版本才支持。</p></blockquote><blockquote><p><code>Webkit</code>内核的浏览器,必须加上<code>-webkit</code>前缀</p></blockquote><figure class="highlight css"><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><code class="hljs css"><span class="hljs-selector-class">.box</span> {<br> <span class="hljs-attribute">display</span>: -webkit-flex; <span class="hljs-comment">/* Safari */</span><br> <span class="hljs-attribute">display</span>: flex;<br> <span class="hljs-attribute">display</span>: inline-flex;<br>}<br></code></pre></td></tr></table></figure><h3 id="二、基本概念"><a href="#二、基本概念" class="headerlink" title="二、基本概念"></a>二、基本概念</h3><ol><li><p>采用<code>Flex</code>布局的元素,称为<code>Flex容器(flex container)</code>,简称”容器”。它的所有子元素自动成为容器成员,称为<code>Flex 项目(flex item)</code>,简称”项目”。</p></li><li><p>容器默认存在两根轴:水平的主轴<code>(main axis)</code>和垂直的交叉轴<code>(cross axis)</code>。主轴的开始位置(与边框的交叉点)叫做<code>main start</code>,结束位置叫做<code>main end</code>;交叉轴的开始位置叫做<code>cross start</code>,结束位置叫做<code>cross end</code>。</p></li><li><p>项目默认沿主轴排列。单个项目占据的主轴空间叫做<code>main size</code>,占据的交叉轴空间叫做<code>cross size</code>。</p></li></ol><h4 id="1、容器属性"><a href="#1、容器属性" class="headerlink" title="1、容器属性"></a>1、容器属性</h4><h5 id="1-flex-direction"><a href="#1-flex-direction" class="headerlink" title="1. flex-direction"></a>1. <code>flex-direction</code></h5><blockquote><p><code>flex-direction</code>属性决定主轴的方向(即项目的排列方向)。</p></blockquote><figure class="highlight pgsql"><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><code class="hljs pgsql">.box {<br> flex-direction: <span class="hljs-keyword">row</span> | <span class="hljs-keyword">row</span>-<span class="hljs-keyword">reverse</span> | <span class="hljs-keyword">column</span> | <span class="hljs-keyword">column</span>-<span class="hljs-keyword">reverse</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li><code>row</code>(默认值):主轴为水平方向,起点在左端。</li><li><code>row-reverse</code>:主轴为水平方向,起点在右端。</li><li><code>column</code>:主轴为垂直方向,起点在上沿。</li><li><code>column-reverse</code>:主轴为垂直方向,起点在下沿。</li></ul><h5 id="2-flex-wrap"><a href="#2-flex-wrap" class="headerlink" title="2. flex-wrap"></a>2. <code>flex-wrap</code></h5><blockquote><p>默认情况下,项目都排在一条线(又称”轴线”)上。<code>flex-wrap</code>属性定义,如果一条轴线排不下,如何换行。</p></blockquote><figure class="highlight lua"><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><code class="hljs lua">.box{<br> flex-<span class="hljs-built_in">wrap</span>: nowrap | <span class="hljs-built_in">wrap</span> | <span class="hljs-built_in">wrap</span>-<span class="hljs-built_in">reverse</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>nowrap(默认):不换行。</li><li>wrap:换行,第一行在上方。</li><li>wrap-reverse:换行,第一行在下方。</li></ul><h5 id="3-flex-flow"><a href="#3-flex-flow" class="headerlink" title="3. flex-flow"></a>3. <code>flex-flow</code></h5><blockquote><p><code>flex-flow</code>属性是<code>flex-direction</code>属性和<code>flex-wrap</code>属性的简写形式,默认值为<code>row nowrap</code>。</p></blockquote><h5 id="4-justify-content"><a href="#4-justify-content" class="headerlink" title="4. justify-content"></a>4. <code>justify-content</code></h5><blockquote><p><code>justify-content</code>属性定义了项目在主轴上的对齐方式。</p></blockquote><figure class="highlight applescript"><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><code class="hljs applescript">.box {<br> justify-content: flex-start | flex-<span class="hljs-keyword">end</span> | center | <span class="hljs-literal">space</span>-<span class="hljs-keyword">between</span> | <span class="hljs-literal">space</span>-<span class="hljs-keyword">around</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li><code>flex-start</code>(默认值):左对齐</li><li><code>flex-end</code>:右对齐</li><li><code>center</code>: 居中</li><li><code>space-between</code>:两端对齐,项目之间的间隔都相等。</li><li><code>space-around</code>:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。</li></ul><h5 id="5-align-items"><a href="#5-align-items" class="headerlink" title="5. align-items"></a>5. <code>align-items</code></h5><blockquote><p><code>align-items</code>属性定义项目在交叉轴上如何对齐。</p></blockquote><figure class="highlight coq"><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><code class="hljs coq">.box {<br> align-items: flex-start | <span class="hljs-type">flex</span>-<span class="hljs-keyword">end</span> | <span class="hljs-type">center</span> | <span class="hljs-type">baseline</span> | <span class="hljs-type">stretch</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li><code>flex-start</code>:交叉轴的起点对齐。</li><li><code>flex-end</code>:交叉轴的终点对齐。</li><li><code>center</code>:交叉轴的中点对齐。</li><li><code>baseline</code>: 项目的第一行文字的基线对齐。</li><li><code>stretch</code>(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。</li></ul><h5 id="6-align-content"><a href="#6-align-content" class="headerlink" title="6. align-content"></a>6. <code>align-content</code></h5><blockquote><p><code>align-content</code>属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。</p></blockquote><figure class="highlight coq"><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><code class="hljs coq">.box {<br> align-content: flex-start | <span class="hljs-type">flex</span>-<span class="hljs-keyword">end</span> | <span class="hljs-type">center</span> | <span class="hljs-type">space</span>-between | <span class="hljs-type">space</span>-around | <span class="hljs-type">stretch</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li><code>flex-start</code>:与交叉轴的起点对齐。</li><li><code>flex-end</code>:与交叉轴的终点对齐。</li><li><code>center</code>:与交叉轴的中点对齐。</li><li><code>space-between</code>:与交叉轴两端对齐,轴线之间的间隔平均分布。</li><li><code>space-around</code>:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。</li><li><code>stretch</code>(默认值):轴线占满整个交叉轴。</li></ul><div style="color: red;">如果设置flex-wrap不换行,那么没有交叉轴,该属性失效 </div><h4 id="2、项目属性"><a href="#2、项目属性" class="headerlink" title="2、项目属性"></a>2、项目属性</h4><h5 id="1-order"><a href="#1-order" class="headerlink" title="1. order"></a>1. <code>order</code></h5><blockquote><p><code>order</code>属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。</p></blockquote><figure class="highlight dts"><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><code class="hljs dts">.<span class="hljs-class">item </span>{<br><span class="hljs-symbol"> order:</span> <span class="hljs-params"><integer></span>;<br>}<br></code></pre></td></tr></table></figure><div style="color: red;">同一个容器内的所有项目参与排序</div><h5 id="2-flex-grow"><a href="#2-flex-grow" class="headerlink" title="2. flex-grow"></a>2. <code>flex-grow</code></h5><blockquote><p><code>flex-grow</code>属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。</p></blockquote><blockquote><p>如果所有项目的<code>flex-grow</code>属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的<code>flex-grow</code>属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。</p></blockquote><figure class="highlight css"><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><code class="hljs css"><span class="hljs-selector-class">.item</span> {<br> <span class="hljs-attribute">flex-grow</span>: <number>; <span class="hljs-comment">/* default 0 */</span><br>}<br></code></pre></td></tr></table></figure><h5 id="3-flex-shrink"><a href="#3-flex-shrink" class="headerlink" title="3. flex-shrink"></a>3. <code>flex-shrink</code></h5><blockquote><p><code>flex-shrink</code>属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。</p></blockquote><blockquote><p>如果所有项目的<code>flex-shrink</code>属性都为1,当空间不足时,都将等比例缩小。如果一个项目的<code>flex-shrink</code>属性为0,其他项目都为1,则空间不足时,前者不缩小。</p></blockquote><blockquote><p>负值对该属性无效。</p></blockquote><figure class="highlight css"><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><code class="hljs css"><span class="hljs-selector-class">.item</span> {<br> <span class="hljs-attribute">flex-shrink</span>: <number>; <span class="hljs-comment">/* default 1 */</span><br>}<br></code></pre></td></tr></table></figure><h5 id="4-flex-basis"><a href="#4-flex-basis" class="headerlink" title="4. flex-basis"></a>4. <code>flex-basis</code></h5><blockquote><p><code>flex-basis</code>属性定义了在分配多余空间之前,项目占据的主轴空间<code>(main size)</code>。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为<code>auto</code>,即项目的本来大小。</p></blockquote><blockquote><p>它可以设为跟<code>width</code>或<code>height</code>属性一样的值(比如<code>350px</code>),则项目将占据固定空间。</p></blockquote><figure class="highlight css"><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><code class="hljs css"><span class="hljs-selector-class">.item</span> {<br> <span class="hljs-attribute">flex-basis</span>: <length> | auto; <span class="hljs-comment">/* default auto */</span><br>}<br></code></pre></td></tr></table></figure><ol start="5"><li><code>flex</code></li></ol><blockquote><p><code>flex</code>属性是<code>flex-grow</code>, <code>flex-shrink</code>和<code>flex-basis</code>的简写,默认值为<code>0 1 auto</code>。后两个属性可选。</p></blockquote><figure class="highlight sml"><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><code class="hljs sml">.item {<br> flex: none | [ <<span class="hljs-symbol">'flex</span>-grow'> <<span class="hljs-symbol">'flex</span>-shrink'>? || <<span class="hljs-symbol">'flex</span>-basis'> ]<br>}<br></code></pre></td></tr></table></figure><blockquote><p>该属性有两个快捷值:<code>auto (1 1 auto)</code>和<code>none (0 0 auto)</code>。</p></blockquote><blockquote><div style="color: red;">建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。</div></blockquote><ol start="6"><li><code>align-self</code></li></ol><blockquote><p><code>align-self</code>属性允许单个项目有与其他项目不一样的对齐方式,可覆盖<code>align-items</code>属性。默认值为<code>auto</code>,表示继承父元素的<code>align-items</code>属性,如果没有父元素,则等同于<code>stretch</code>。</p></blockquote><figure class="highlight coq"><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><code class="hljs coq">.item {<br> align-self: <span class="hljs-built_in">auto</span> | <span class="hljs-type">flex</span>-start | <span class="hljs-type">flex</span>-<span class="hljs-keyword">end</span> | <span class="hljs-type">center</span> | <span class="hljs-type">baseline</span> | <span class="hljs-type">stretch</span>;<br>}<br></code></pre></td></tr></table></figure>]]></content>
<categories>
<category>Web</category>
</categories>
<tags>
<tag>Web</tag>
<tag>css</tag>
</tags>
</entry>
<entry>
<title>前端学习日记-log7</title>
<link href="/2019/07/16/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log7/"/>
<url>/2019/07/16/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log7/</url>
<content type="html"><![CDATA[<hr><blockquote><p><em><a href="http://ife.baidu.com/course/detail/id/40">第五天和第六天:三种简历</a></em></p></blockquote><hr><h4 id="第一种"><a href="#第一种" class="headerlink" title="第一种"></a>第一种</h4><p><img src="image_1.png" alt="image_1.png"></p><p>个人思路:</p><ol><li>总体上是左右分栏,默认的流动模型(<code>flow</code>)不太适合,浮动模型(<code>float</code>)和层模型(<code>layer</code>)可以考虑</li><li>层模型不太适合整个右侧一栏的布局,浮动模型代码量较多</li><li>弹性布局(<code>flex</code>)非常适合,代码简单,单需要适配解决老版本的兼容问题,整体代码少</li></ol><p>综上,第一种样式代码如下:</p><figure class="highlight xml"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment"><!-- html --></span><br><span class="hljs-meta"><!DOCTYPE <span class="hljs-meta-keyword">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">title</span>></span>三种简历<span class="hljs-tag"></<span class="hljs-name">title</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"css/test1.css"</span> /></span><br><span class="hljs-tag"></<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">body</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"pageTitleClass"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span>></span>XX<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"infoClass"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"titleClass"</span>></span><br>basicInfo<br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"contentClass"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>name<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>zhangsan<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>gender<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>male<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>position<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>xxxxxxxxxxxxx<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"titleClass"</span>></span><br>phone&email<br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"contentClass"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>phone<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>18600000000<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>email<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>[email protected]<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>homepage<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>xxxxxxxxxxxxxxxxxxxxxxxxx<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"titleClass"</span>></span><br>schools<br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"contentClass"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>Bachelor<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>xxxxxxxxxxxxxxxxxxxxxxxx<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>Postgraduate<span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>xxxxxxxxxxxxxxxxxxxxxxxx<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"titleClass"</span>></span><br>projects<br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"contentClass"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>project name<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>A<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><br><span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>project time<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>xxxx.xx - xxxx.xx<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>project info:<span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span>></span>sssss, ssss, sssss, sssss, ssss, sssss, sssss, ssss, sssss, sssss, ssss, sssss, sssss, ssss, sssss, sssss, ssss, sssss, sssss, ssss, sssss, sssss, ssss, sssss, sssss, ssss, sssss.<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">body</span>></span><br><span class="hljs-tag"></<span class="hljs-name">html</span>></span><br></code></pre></td></tr></table></figure><figure class="highlight css"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><code class="hljs css"><span class="hljs-comment">/* css */</span><br><span class="hljs-selector-tag">body</span> {<br><span class="hljs-attribute">display</span>: flex;<br>}<br><br><span class="hljs-selector-class">.pageTitleClass</span> {<br><span class="hljs-attribute">flex-grow</span>: <span class="hljs-number">0</span>;<br><span class="hljs-attribute">flex-shrink</span>: <span class="hljs-number">0</span>;<br><span class="hljs-attribute">flex-basis</span>: <span class="hljs-number">120px</span>;<br><br><span class="hljs-attribute">background-color</span>: lightgrey;<br>}<br><span class="hljs-selector-class">.pageTitleClass</span> > <span class="hljs-selector-tag">p</span> {<br><span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;<br><span class="hljs-attribute">margin-top</span>: <span class="hljs-number">50px</span>;<br><span class="hljs-attribute">color</span>: white;<br><span class="hljs-attribute">font-size</span>: <span class="hljs-number">30px</span>;<br><span class="hljs-attribute">text-align</span>: center;<br>}<br><br><span class="hljs-selector-class">.infoClass</span> {<br><span class="hljs-attribute">flex-grow</span>: <span class="hljs-number">1</span>;<br><span class="hljs-attribute">flex-shrink</span>: <span class="hljs-number">1</span>;<br><span class="hljs-attribute">flex-basis</span>: auto;<br><br><span class="hljs-attribute">margin-left</span>: <span class="hljs-number">20px</span>;<br><span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">25px</span>;<br>}<br><br><span class="hljs-selector-class">.titleClass</span> {<br><span class="hljs-attribute">font-size</span>: <span class="hljs-number">25px</span>;<br><span class="hljs-attribute">font-weight</span>: bold;<br><span class="hljs-attribute">margin-top</span>: <span class="hljs-number">25px</span>;<br>}<br><br><span class="hljs-selector-class">.contentClass</span> {<br><span class="hljs-attribute">margin-top</span>: <span class="hljs-number">20px</span>;<br><span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>;<br>}<br><span class="hljs-selector-class">.keyClass</span> {<br><span class="hljs-attribute">font-weight</span>: bold;<br>}<br><span class="hljs-selector-class">.valueCalss</span> {<br><span class="hljs-attribute">margin-left</span>: <span class="hljs-number">8px</span>;<br>}<br><span class="hljs-selector-class">.contentClass</span> > <span class="hljs-selector-tag">span</span> {<br><span class="hljs-attribute">margin-right</span>: <span class="hljs-number">40px</span>;<br>}<br><span class="hljs-selector-class">.contentClass</span> > <span class="hljs-selector-tag">p</span> {<br><span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>;<br>}<br><span class="hljs-selector-class">.contentClass</span> > <span class="hljs-selector-tag">div</span> {<br><span class="hljs-attribute">margin</span>: <span class="hljs-number">10px</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h4 id="第二种"><a href="#第二种" class="headerlink" title="第二种"></a>第二种</h4><p><img src="image_2.png" alt="image_2.png"></p><p>个人思路:</p><ol><li>总体上是默认的流动模型(<code>flow</code>),所以总体使用流程模型</li><li>除标题外,每行是左右分栏,所以考虑浮动模型(<code>float</code>)和层模型(<code>layer</code>)</li><li>注意到分割线等细节,浮动模型不适合,考虑每行使用层模型布局</li></ol><p>综上,第二种样式代码如下:</p><figure class="highlight xml"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment"><!-- html --></span><br><span class="hljs-meta"><!DOCTYPE <span class="hljs-meta-keyword">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">title</span>></span>三种简历<span class="hljs-tag"></<span class="hljs-name">title</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"css/test2.css"</span>/></span><br><span class="hljs-tag"></<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">body</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"pageTitleClass"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span>></span>XX<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"cellClass"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"titleClass"</span>></span><br>basicInfo<br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"contentClass"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>name<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>zhangsan<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>gender<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>male<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>position<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>xxxxxxxxxxxxx<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"cellClass"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"titleClass"</span>></span><br>phone&email<br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"contentClass"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>phone<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>18600000000<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>email<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>[email protected]<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>homepage<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>xxxxxxxxxxxxxxxxxxxxxxxxx<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"cellClass"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"titleClass"</span>></span><br>schools<br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"contentClass"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>Bachelor<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>xxxxxxxxxxxxxxxxxxxxxxxx<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"keyClass"</span>></span>Postgraduate<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"valueCalss"</span>></span>xxxxxxxxxxxxxxxxxxxxxxxx<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">body</span>></span><br><span class="hljs-tag"></<span class="hljs-name">html</span>></span><br><br></code></pre></td></tr></table></figure><figure class="highlight css"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><code class="hljs css"><span class="hljs-comment">/* css */</span><br><span class="hljs-selector-class">.pageTitleClass</span> {<br><span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;<br><span class="hljs-attribute">height</span>: <span class="hljs-number">60px</span>;<br><span class="hljs-attribute">background-color</span>: darkgray;<br><span class="hljs-attribute">line-height</span>: <span class="hljs-number">60px</span>;<br>}<br><span class="hljs-selector-class">.pageTitleClass</span> > <span class="hljs-selector-tag">p</span> {<br><span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">20px</span>;<br><span class="hljs-attribute">color</span>: white;<br><span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>;<br>}<br><br><span class="hljs-selector-class">.cellClass</span> {<br><span class="hljs-attribute">margin-top</span>: <span class="hljs-number">1px</span>;<br><span class="hljs-attribute">height</span>: <span class="hljs-number">100px</span>;<br><span class="hljs-attribute">background</span>: white;<br><span class="hljs-attribute">position</span>: relative;<br><span class="hljs-attribute">background</span>: lightgray;<br>}<br><br><span class="hljs-selector-class">.titleClass</span> {<br><span class="hljs-attribute">width</span>: <span class="hljs-number">100px</span>;<br><span class="hljs-attribute">line-height</span>: <span class="hljs-number">100px</span>;<br><span class="hljs-attribute">font-size</span>: <span class="hljs-number">15px</span>;<br><span class="hljs-attribute">font-weight</span>: bold;<br><span class="hljs-attribute">text-align</span>: center;<br>}<br><br><span class="hljs-selector-class">.contentClass</span> {<br><span class="hljs-attribute">position</span>: absolute;<br><span class="hljs-attribute">top</span>: <span class="hljs-number">1px</span>;<br><span class="hljs-attribute">left</span>: <span class="hljs-number">100px</span>;<br><span class="hljs-attribute">right</span>: <span class="hljs-number">0</span>;<br><span class="hljs-attribute">bottom</span>: <span class="hljs-number">0</span>;<br><br><span class="hljs-attribute">padding-top</span>: <span class="hljs-number">12px</span>;<br><span class="hljs-attribute">padding-left</span>: <span class="hljs-number">10px</span>;<br><span class="hljs-attribute">background</span>: white;<br>}<br><br><span class="hljs-selector-class">.keyClass</span> {<br><span class="hljs-attribute">font-weight</span>: bold;<br>}<br><span class="hljs-selector-class">.valueCalss</span> {<br><span class="hljs-attribute">margin-left</span>: <span class="hljs-number">8px</span>;<br>}<br></code></pre></td></tr></table></figure><p><span style="color: lightgray;"><em>未完待续</em></span></p>]]></content>
<categories>
<category>Web</category>
</categories>
<tags>
<tag>学习日记</tag>
<tag>Web</tag>
</tags>
</entry>
<entry>
<title>h5页面上文字超出后如何显示省略号</title>
<link href="/2019/06/24/h5%E9%A1%B5%E9%9D%A2%E4%B8%8A%E6%96%87%E5%AD%97%E8%B6%85%E5%87%BA%E5%90%8E%E5%A6%82%E4%BD%95%E6%98%BE%E7%A4%BA%E7%9C%81%E7%95%A5%E5%8F%B7/"/>
<url>/2019/06/24/h5%E9%A1%B5%E9%9D%A2%E4%B8%8A%E6%96%87%E5%AD%97%E8%B6%85%E5%87%BA%E5%90%8E%E5%A6%82%E4%BD%95%E6%98%BE%E7%A4%BA%E7%9C%81%E7%95%A5%E5%8F%B7/</url>
<content type="html"><![CDATA[<h4 id="一、单行文字"><a href="#一、单行文字" class="headerlink" title="一、单行文字"></a>一、单行文字</h4><p>代码如下</p><figure class="highlight xml"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment"><!-- html --></span><br><span class="hljs-meta"><!DOCTYPE <span class="hljs-meta-keyword">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">title</span>></span>testOverFlow<span class="hljs-tag"></<span class="hljs-name">title</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">style</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span>></span><br>.container {<br><span class="css"><span class="hljs-attribute">margin-top</span>: <span class="hljs-number">10px</span>;</span><br><span class="css"><span class="hljs-attribute">width</span>: <span class="hljs-number">200px</span>;</span><br><span class="css"><span class="hljs-attribute">height</span>: <span class="hljs-number">44px</span>;</span><br><span class="css"><span class="hljs-attribute">line-height</span>: <span class="hljs-number">44px</span>;</span><br><span class="css"><span class="hljs-attribute">background-color</span>: lightgray;</span><br>}<br><span class="css"><span class="hljs-comment">/* 单行样式 */</span></span><br>#singleTextDiv {<br><span class="css"><span class="hljs-attribute">text-overflow</span>: ellipsis;</span><br><span class="css"><span class="hljs-attribute">white-space</span>: nowrap;</span><br><span class="css"><span class="hljs-attribute">overflow</span>: hidden;</span><br>}<br>#singleP {<br><span class="css"><span class="hljs-attribute">text-overflow</span>: ellipsis;</span><br><span class="css"><span class="hljs-attribute">white-space</span>: nowrap;</span><br><span class="css"><span class="hljs-attribute">overflow</span>: hidden;</span><br>}<br>#singleSpan {<br><span class="css"><span class="hljs-attribute">display</span>: block;</span><br><span class="css"><span class="hljs-attribute">text-overflow</span>: ellipsis;</span><br><span class="css"><span class="hljs-attribute">white-space</span>: nowrap;</span><br><span class="css"><span class="hljs-attribute">overflow</span>: hidden;</span><br>}<br><span class="hljs-tag"></<span class="hljs-name">style</span>></span><br><span class="hljs-tag"></<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">body</span>></span><br><span class="hljs-comment"><!-- 单行文字 --></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"singleTextDiv"</span>></span><br>少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书<br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"singleP"</span>></span>少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"singleSpan"</span>></span>少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">body</span>></span><br><span class="hljs-tag"></<span class="hljs-name">html</span>></span><br></code></pre></td></tr></table></figure><p><code>div</code>和<code>p</code>是块级元素,<code>span</code>是内联元素,对块级元素设置<code>text-overflow</code>、<code>white-space</code>、<code>overflow</code>三个属性标签即可</p><h4 id="二、多行文字"><a href="#二、多行文字" class="headerlink" title="二、多行文字"></a>二、多行文字</h4><figure class="highlight xml"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment"><!-- html --></span><br><span class="hljs-meta"><!DOCTYPE <span class="hljs-meta-keyword">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">title</span>></span>testOverFlow<span class="hljs-tag"></<span class="hljs-name">title</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">style</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span>></span><br>.container {<br><span class="css"><span class="hljs-attribute">margin-top</span>: <span class="hljs-number">10px</span>;</span><br><span class="css"><span class="hljs-attribute">width</span>: <span class="hljs-number">200px</span>;</span><br><span class="css"><span class="hljs-attribute">height</span>: <span class="hljs-number">44px</span>;</span><br><span class="css"><span class="hljs-attribute">line-height</span>: <span class="hljs-number">44px</span>;</span><br><span class="css"><span class="hljs-attribute">background-color</span>: lightgray;</span><br>}<br><span class="css"><span class="hljs-comment">/* 多行样式 */</span></span><br>#doubleP {<br><span class="css"><span class="hljs-attribute">line-height</span>: <span class="hljs-number">22px</span>;</span><br><span class="css"><span class="hljs-attribute">text-overflow</span>: ellipsis;</span><br><span class="css"><span class="hljs-attribute">overflow</span>: hidden;</span><br><span class="css"><span class="hljs-attribute">display</span>: -webkit-box;</span><br><span class="css">-webkit-box-orient: vertical;</span><br><span class="css">-webkit-line-clamp:<span class="hljs-number">2</span>;</span><br>}<br>#doubleSpan {<br><span class="css"><span class="hljs-attribute">display</span>: block;</span><br><span class="css"><span class="hljs-attribute">line-height</span>: <span class="hljs-number">22px</span>;</span><br><span class="css"><span class="hljs-attribute">text-overflow</span>: ellipsis;</span><br><span class="css"><span class="hljs-attribute">overflow</span>: hidden;</span><br><span class="css"><span class="hljs-attribute">display</span>: -webkit-box;</span><br><span class="css">-webkit-box-orient: vertical;</span><br><span class="css">-webkit-line-clamp:<span class="hljs-number">2</span>;</span><br>}<br><span class="hljs-tag"></<span class="hljs-name">style</span>></span><br><span class="hljs-tag"></<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">body</span>></span><br><span class="hljs-comment"><!-- 多行文字 --></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"doubleP"</span>></span>少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"doubleSpan"</span>></span>少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"></<span class="hljs-name">body</span>></span><br><span class="hljs-tag"></<span class="hljs-name">html</span>></span><br></code></pre></td></tr></table></figure><h6 id="注意:"><a href="#注意:" class="headerlink" title="注意:"></a><div style="color: red;">注意:</div></h6><ol><li><code>-webkit</code>代表<code>Safari</code>、<code>Chrome</code>等浏览器的私有属性</li><li><code>-webkit-line-clamp</code>用来限制要显示的行数,但是这是一个不规范的属性,必须组合其他的<code>-webkit</code>属性才能达到效果</li></ol>]]></content>
<categories>
<category>Web</category>
</categories>
<tags>
<tag>Web</tag>
<tag>css</tag>
</tags>
</entry>
<entry>
<title>前端学习日记-log6</title>
<link href="/2019/06/24/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log6/"/>
<url>/2019/06/24/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log6/</url>
<content type="html"><![CDATA[<h1 id="百度前端技术学院"><a href="#百度前端技术学院" class="headerlink" title="百度前端技术学院"></a><a href="http://ife.baidu.com/">百度前端技术学院</a></h1><hr><blockquote><p><em><a href="http://ife.baidu.com/course/detail/id/28">第一天:为什么有那么多人要做前端?</a></em></p></blockquote><hr><p>一个普通网站访问的过程<br>简单概括一下,对于我们普通的网站访问,涉及到的技术就是:</p><ol><li>用户操作浏览器访问,浏览器向服务器发出一个<code>HTTP</code>请求;</li><li>服务器接收到<code>HTTP</code>请求,<code>Web Server</code>进行相应的初步处理,使用服务器脚本生成页面;</li><li>服务器脚本(利用<code>Web Framework</code>)调用本地和客户端传来的数据,生成页面;</li><li><code>Web Server</code>将生成的页面作为<code>HTTP</code>响应的<code>body</code>,根据不同的处理结果生成<code>HTTP header</code>,发回给客户端;</li><li>客户端(浏览器)接收到<code>HTTP</code>响应,通常第一个请求得到的<code>HTTP</code>响应的<code>body</code>里是<code>HTML</code>代码,于是对<code>HTML</code>代码开始解析;</li><li>解析过程中遇到引用的服务器上的资源(额外的<code>CSS</code>、<code>JS</code>代码,图片、音视频,附件等),再向<code>Web Server</code>发送请求,<code>Web Server</code>找到对应的文件,发送回来;</li><li>浏览器解析<code>HTML</code>包含的内容,用得到的<code>CSS</code>代码进行外观上的进一步渲染,<code>JS</code>代码也可能会对外观进行一定的处理;</li><li>用户与页面交互(点击,悬停等等)时,<code>JS</code>代码对此作出一定的反应,添加特效与动画;</li><li>交互的过程中可能需要向服务器索取或提交额外的数据(局部的刷新,类似微博的新消息通知),一般不是跳转就是通过<code>JS</code>代码(响应某个动作或者定时)向<code>Web Server</code>发送请求,<code>Web Server</code>再用服务器脚本进行处理(生成资源<code>or</code>写入数据之类的),把资源返回给客户端,客户端用得到的资源来实现动态效果或其他改变。</li></ol><p>注意这只是小网站里比较常见的模型,大网站为了解决规模问题还会有很多处理,每个环节都会有一些细微的差异,中间还会使用各种各样的工具减轻服务器的压力,提高效率,方便日常维护</p><hr><blockquote><p><em><a href="http://ife.baidu.com/course/detail/id/36">第二天:给自己做一个在线简历吧</a></em></p></blockquote><hr><ol><li><a href="http://zhangwenli.com/cv/cn.html">羡辙的简历</a></li><li><code>Web</code>语义化,<a href="http://justineo.github.io/slideshows/semantic-html/#/">Semantic HTML-顾轶灵</a></li></ol><figure class="highlight xml"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta"><!DOCTYPE <span class="hljs-meta-keyword">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">title</span>></span>简历<span class="hljs-tag"></<span class="hljs-name">title</span>></span><br><span class="hljs-tag"></<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">body</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">""</span>></span><br><span class="hljs-tag"><<span class="hljs-name">h3</span>></span>个人信息<span class="hljs-tag"></<span class="hljs-name">h3</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">""</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span>姓名:张三<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span>性别:男<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">""</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span>手机:18600000000<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"><<span class="hljs-name">span</span>></span>邮箱:[email protected]<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">""</span>></span><br><span class="hljs-tag"><<span class="hljs-name">h3</span>></span>项目列表<span class="hljs-tag"></<span class="hljs-name">h3</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">""</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span>></span>项目名称:A<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">p</span>></span>项目时间:xxxx.xx - xxxx.xx<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">p</span>></span>项目描述:<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">p</span>></span>少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">""</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span>></span>项目名称:B<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">p</span>></span>项目时间:xxxx.xx - xxxx.xx<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">p</span>></span>项目描述:<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">p</span>></span>少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">body</span>></span><br><span class="hljs-tag"></<span class="hljs-name">html</span>></span><br></code></pre></td></tr></table></figure><hr><blockquote><p><em><a href="http://ife.baidu.com/course/detail/id/37">第三天:让简历有点色彩</a></em></p></blockquote><hr><figure class="highlight xml"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment"><!-- html --></span><br><span class="hljs-meta"><!DOCTYPE <span class="hljs-meta-keyword">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">title</span>></span>简历<span class="hljs-tag"></<span class="hljs-name">title</span>></span><br><span class="hljs-tag"><<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"css/test.css"</span>/></span><br><span class="hljs-tag"></<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">body</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"infoCell"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">h3</span>></span>个人信息<span class="hljs-tag"></<span class="hljs-name">h3</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"cell"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"halfInfo"</span>></span>姓名:张三<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"halfInfo"</span>></span>性别:男<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"cell"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"halfInfo"</span>></span>手机:18600000000<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"halfInfo"</span>></span>邮箱:[email protected]<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"projectCell"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">h3</span>></span>项目列表<span class="hljs-tag"></<span class="hljs-name">h3</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"cell"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"halfInfo"</span>></span>项目名称:A<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"halfInfo"</span>></span>项目时间:xxxx.xx - xxxx.xx<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">p</span>></span>项目描述:<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span>></span>少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"cell"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"halfInfo"</span>></span>项目名称:B<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"><<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"halfInfo"</span>></span>项目时间:xxxx.xx - xxxx.xx<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">p</span>></span>项目描述:<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">p</span>></span>少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书少时诵诗书<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">body</span>></span><br><span class="hljs-tag"></<span class="hljs-name">html</span>></span><br></code></pre></td></tr></table></figure><figure class="highlight css"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><code class="hljs css"><span class="hljs-comment">/* css */</span><br>* {<br><span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;<br>}<br><br><span class="hljs-selector-tag">body</span> {<br><span class="hljs-attribute">margin</span>: <span class="hljs-number">8px</span> <span class="hljs-number">8px</span> <span class="hljs-number">8px</span> <span class="hljs-number">8px</span>;<br>}<br><br><span class="hljs-selector-tag">h3</span> {<br><span class="hljs-attribute">font-weight</span>: bold;<br><span class="hljs-attribute">background-color</span>: darkslategray;<br><span class="hljs-attribute">color</span>: white;<br><span class="hljs-attribute">width</span>: <span class="hljs-number">100px</span>;<br><span class="hljs-attribute">height</span>: <span class="hljs-number">28px</span>;<br><span class="hljs-attribute">font-size</span>: <span class="hljs-number">20px</span>;<br><span class="hljs-attribute">text-align</span>: center;<br><span class="hljs-attribute">margin-top</span>: <span class="hljs-number">15px</span>;<br>}<br><br><span class="hljs-selector-class">.cell</span> {<br><span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;<br><span class="hljs-attribute">height</span>: <span class="hljs-number">38px</span>;<br>}<br><br><span class="hljs-selector-class">.halfInfo</span> {<br><span class="hljs-attribute">float</span>: left;<br><span class="hljs-attribute">width</span>: <span class="hljs-number">50%</span>;<br><span class="hljs-attribute">height</span>: <span class="hljs-number">38px</span>;<br><span class="hljs-attribute">line-height</span>: <span class="hljs-number">38px</span>;<br><br><span class="hljs-comment">/* 超出部分显示省略号 */</span><br><span class="hljs-attribute">text-overflow</span>: ellipsis;<br><span class="hljs-attribute">white-space</span>: nowrap;<br> <span class="hljs-attribute">overflow</span>: hidden;<br>}<br></code></pre></td></tr></table></figure><p><span style="color: lightgray;"><em>未完待续</em></span></p>]]></content>
<categories>
<category>Web</category>
</categories>
<tags>
<tag>学习日记</tag>
<tag>Web</tag>
</tags>
</entry>
<entry>
<title>前端学习日记-log5</title>
<link href="/2019/06/12/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log5/"/>
<url>/2019/06/12/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log5/</url>
<content type="html"><![CDATA[<blockquote><p><em>继续上次的地方继续往下学习</em></p></blockquote><hr><h2 id="日志随笔"><a href="#日志随笔" class="headerlink" title="日志随笔"></a>日志随笔</h2><h3 id="7-节点类型判断"><a href="#7-节点类型判断" class="headerlink" title="7. 节点类型判断"></a>7. 节点类型判断</h3><ul><li>isElement 判断元素节点</li></ul><figure class="highlight xml"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta"><!DOCTYPE <span class="hljs-meta-keyword">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">title</span>></span><span class="hljs-tag"></<span class="hljs-name">title</span>></span><br><span class="hljs-tag"></<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">body</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"test"</span>></span><br>aaa<br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span>></span><br><span class="javascript"><span class="hljs-keyword">var</span> testDiv = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'div'</span>);</span><br><span class="javascript"><span class="hljs-keyword">var</span> isElement = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">obj</span>) </span>{</span><br>if (obj && obj.nodeType === 1) {<br><span class="javascript"><span class="hljs-keyword">if</span> (<span class="hljs-built_in">window</span>.Node && (obj <span class="hljs-keyword">instanceof</span> Node)) {</span><br><span class="javascript"><span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;</span><br>}<br><span class="javascript"><span class="hljs-keyword">try</span>{</span><br>testDiv.appendChild(obj);<br>testDiv.removeChild(obj);<br><span class="javascript">}<span class="hljs-keyword">catch</span>(e){</span><br><span class="javascript"><span class="hljs-comment">//TODO handle the exception</span></span><br><span class="javascript"><span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;</span><br>}<br><span class="javascript"><span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;</span><br>}<br><span class="javascript"><span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;</span><br>}<br><span class="javascript"><span class="hljs-keyword">var</span> a = {</span><br>nodeType: 1<br>}<br><span class="javascript"><span class="hljs-built_in">console</span>.log(isElement(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"test"</span>))); <span class="hljs-comment">// true</span></span><br><span class="javascript"><span class="hljs-built_in">console</span>.log(isElement(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"test"</span>).nextSibling)); <span class="hljs-comment">// false</span></span><br><span class="javascript"><span class="hljs-built_in">console</span>.log(isElement(a)); <span class="hljs-comment">// false</span></span><br><span class="hljs-tag"></<span class="hljs-name">script</span>></span><br><span class="hljs-tag"></<span class="hljs-name">body</span>></span><br><span class="hljs-tag"></<span class="hljs-name">html</span>></span><br></code></pre></td></tr></table></figure><ul><li>isHTML</li><li>isXML</li></ul><figure class="highlight xml"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta"><!DOCTYPE <span class="hljs-meta-keyword">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">title</span>></span>isXML<span class="hljs-tag"></<span class="hljs-name">title</span>></span><br><span class="hljs-tag"></<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">body</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"test"</span>></span><br>isXML<br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-comment"><!-- 这是一个注释节点 --></span><br><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span>></span><br><span class="javascript"><span class="hljs-keyword">var</span> isXML = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">elem</span>) </span>{</span><br><span class="javascript"><span class="hljs-keyword">var</span> documentElement = elem && (elem.ownerDocument || elem).documentElement;</span><br><span class="javascript"><span class="hljs-keyword">return</span> documentElement ? documentElement.nodeName !== <span class="hljs-string">"HTML"</span> : <span class="hljs-literal">false</span></span><br>}<br><span class="javascript"><span class="hljs-built_in">console</span>.log(isXML(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"test"</span>)));</span><br><br><span class="javascript"><span class="hljs-keyword">try</span>{</span><br><span class="javascript"><span class="hljs-keyword">var</span> doc = <span class="hljs-built_in">document</span>.implementation.createDocument(<span class="hljs-literal">null</span>, <span class="hljs-string">"HTML"</span>, <span class="hljs-literal">null</span>);</span><br><span class="javascript"><span class="hljs-built_in">console</span>.log(doc.documentElement);</span><br><span class="javascript"><span class="hljs-built_in">console</span>.log(isXML(doc));</span><br><span class="javascript">}<span class="hljs-keyword">catch</span>(e){</span><br><span class="javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">"不支持createDocument方法"</span>)</span><br>}<br><br><span class="javascript"><span class="hljs-keyword">var</span> isXML2 = <span class="hljs-built_in">window</span>.HTMLDocument ? <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">doc</span>) </span>{</span><br><span class="javascript"><span class="hljs-keyword">return</span> !(doc <span class="hljs-keyword">instanceof</span> HTMLDocument);</span><br><span class="javascript">} : <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">doc</span>) </span>{</span><br><span class="javascript"><span class="hljs-keyword">return</span> <span class="hljs-string">"selectNodes"</span> <span class="hljs-keyword">in</span> doc;</span><br>}<br><br><span class="javascript"><span class="hljs-keyword">var</span> isXML3 = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">doc</span>) </span>{</span><br><span class="javascript"><span class="hljs-keyword">return</span> doc.createElement(<span class="hljs-string">"p"</span>).nodeName !== doc.createElement(<span class="hljs-string">"p"</span>).nodeName;</span><br>}<br><span class="javascript"><span class="hljs-built_in">console</span>.log(isXML3(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"test"</span>)));</span><br><span class="hljs-tag"></<span class="hljs-name">script</span>></span><br><span class="hljs-tag"></<span class="hljs-name">body</span>></span><br><span class="hljs-tag"></<span class="hljs-name">html</span>></span><br></code></pre></td></tr></table></figure><ul><li>contains</li></ul><figure class="highlight xml"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta"><!DOCTYPE <span class="hljs-meta-keyword">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">title</span>></span>contains<span class="hljs-tag"></<span class="hljs-name">title</span>></span><br><span class="hljs-tag"></<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">body</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"p-node"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"c-node"</span>></span><br>子节点内容<br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span>></span><br><span class="javascript"><span class="hljs-keyword">var</span> pNode = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"p-node"</span>);</span><br><span class="javascript"><span class="hljs-keyword">var</span> cNode = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"c-node"</span>);</span><br><span class="javascript"><span class="hljs-built_in">console</span>.log(pNode.contains(cNode)); <span class="hljs-comment">// IE老版本不支持contains方法</span></span><br><span class="javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">document</span>.contains(cNode));</span><br><br><span class="javascript"><span class="hljs-comment">// 重新实现</span></span><br><span class="javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fixContains</span>(<span class="hljs-params">a, b</span>) </span>{</span><br><span class="javascript"><span class="hljs-keyword">try</span>{</span><br><span class="javascript"><span class="hljs-keyword">while</span> (b = b.parentNode){</span><br>if (b === a) {<br><span class="javascript"><span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;</span><br>}<br>}<br><span class="javascript"><span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;</span><br><span class="javascript">}<span class="hljs-keyword">catch</span>(e){</span><br><span class="javascript"><span class="hljs-comment">//TODO handle the exception</span></span><br><span class="javascript"><span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;</span><br>}<br>}<br><span class="javascript"><span class="hljs-built_in">console</span>.log(fixContains(pNode, cNode));</span><br><span class="javascript"><span class="hljs-built_in">console</span>.log(fixContains(<span class="hljs-built_in">document</span>, cNode));</span><br><span class="javascript"><span class="hljs-keyword">var</span> cNode1 = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"c-node"</span>).childNodes[<span class="hljs-number">0</span>];</span><br><span class="javascript"><span class="hljs-built_in">console</span>.log(fixContains(pNode, cNode1));</span><br><span class="javascript"><span class="hljs-built_in">console</span>.log(fixContains(<span class="hljs-built_in">document</span>, cNode1));</span><br><span class="hljs-tag"></<span class="hljs-name">script</span>></span><br><span class="hljs-tag"></<span class="hljs-name">body</span>></span><br><span class="hljs-tag"></<span class="hljs-name">html</span>></span><br></code></pre></td></tr></table></figure><h3 id="8-DOM节点继承层次"><a href="#8-DOM节点继承层次" class="headerlink" title="8. DOM节点继承层次"></a>8. DOM节点继承层次</h3><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs reasonml">console.log(<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">Object</span>.</span></span>get<span class="hljs-constructor">OwnPropertyNames(<span class="hljs-params">document</span>.<span class="hljs-params">createElement</span>(<span class="hljs-string">"p"</span>)</span>.__proto__));<br>console.log(<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">Object</span>.</span></span>get<span class="hljs-constructor">OwnPropertyNames(<span class="hljs-params">document</span>.<span class="hljs-params">createElement</span>(<span class="hljs-string">"p"</span>)</span>.<span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">__proto__</span>.</span><span class="hljs-module"><span class="hljs-identifier">__proto__</span>)</span></span>);<br></code></pre></td></tr></table></figure><h3 id="9-HTML嵌套规则"><a href="#9-HTML嵌套规则" class="headerlink" title="9. HTML嵌套规则"></a>9. HTML嵌套规则</h3><ul><li>块状元素:一般是其他元素的容器,可以容纳其他块状元素和内联元素,块状元素排斥其他元素同一行,可以设置宽高,例如<code>div</code>、<code>p</code>、<code>ul</code></li><li>内联元素:只能容纳文本或者其他内联元素,允许同一行,设置宽高不起作用,例如<code>a</code>、<code>br</code>、<code>img</code>、<code>input</code>、<code>textarea</code></li></ul><ol><li>块级元素可以包含内联和某些块级元素,内联不能包含块级元素</li><li>块级元素不能放在<code>p</code>元素中</li><li>某些特殊的块级元素只能包含内联,不能包含块级,例如:<code>h1~h6</code>、<code>p</code>、<code>dt</code></li><li><code>li</code>里面可以包含<code>div</code>标签</li><li>块级和块级并列,内联和内联并列</li></ol><p><img src="image_2.png" alt="image_2.png"></p><p><span style="color: lightgray;"><em>未完待续</em></span></p>]]></content>
<categories>
<category>Web</category>
</categories>
<tags>
<tag>学习日记</tag>
<tag>Web</tag>
</tags>
</entry>
<entry>
<title>前端学习日记-log4</title>
<link href="/2019/06/04/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log4/"/>
<url>/2019/06/04/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log4/</url>
<content type="html"><![CDATA[<blockquote><p><em>继续上次的地方继续往下学习</em></p></blockquote><hr><h2 id="日志随笔"><a href="#日志随笔" class="headerlink" title="日志随笔"></a>日志随笔</h2><h3 id="5-浏览器渲染流程"><a href="#5-浏览器渲染流程" class="headerlink" title="5. 浏览器渲染流程"></a>5. 浏览器渲染流程</h3><p><img src="image_1.png" alt="image_1.png"></p><p><img src="image_2.png" alt="image_2.png"></p><h3 id="6-domReady实现"><a href="#6-domReady实现" class="headerlink" title="6. domReady实现"></a>6. domReady实现</h3><p><code>domReady</code>实际上就是获取浏览器渲染过程中<code>DOM</code>树构建完成的时间,在此时间引入<code>js</code>脚本,这样实现页面的无缝渲染</p><ul><li><p><code>setTimeout</code>定时器,定时器制定一个固定时间,来渲染页面</p></li><li><p><code>window.onload</code>方法,资源加载完成后才会触发,包括外部资源,外部资源较多时,等待时间较长,效果不好</p></li><li><p><code>$(document).ready</code>方法,<code>jqurey</code>框架中的方法,此处暂时没有学到这个框架</p></li><li><p><code>DOMContentLoaded</code>方法</p></li></ul><figure class="highlight xml"><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></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta"><!DOCTYPE <span class="hljs-meta-keyword">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /></span><br><span class="hljs-tag"><<span class="hljs-name">title</span>></span><span class="hljs-tag"></<span class="hljs-name">title</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"js/myDomReady.js"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span><br><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span>></span><br><span class="javascript">myReady(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{</span><br><span class="javascript"><span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'header'</span>).style.color = <span class="hljs-string">'red'</span>;</span><br>});<br><span class="hljs-tag"></<span class="hljs-name">script</span>></span><br><span class="hljs-tag"></<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">body</span>></span><br><span class="hljs-tag"><<span class="hljs-name">h1</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"header"</span>></span>字体颜色<span class="hljs-tag"></<span class="hljs-name">h1</span>></span><br><span class="hljs-tag"></<span class="hljs-name">body</span>></span><br><span class="hljs-tag"></<span class="hljs-name">html</span>></span><br></code></pre></td></tr></table></figure><figure class="highlight javascript"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">// myDomReady.js</span><br><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">myReady</span>(<span class="hljs-params">fn</span>) </span>{<br><span class="hljs-comment">// 区分浏览器</span><br><span class="hljs-keyword">if</span> (<span class="hljs-built_in">document</span>.addEventListener) {<br><span class="hljs-comment">// 现代浏览器</span><br><span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'DOMContentLoaded'</span>, fn, <span class="hljs-literal">false</span>);<br>} <span class="hljs-keyword">else</span>{<br>IEContentReady(fn);<br>}<br><br><span class="hljs-comment">//IE模拟</span><br><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">IEContentReady</span>(<span class="hljs-params">fn</span>) </span>{<br><span class="hljs-keyword">var</span> d = <span class="hljs-built_in">window</span>.document;<br><span class="hljs-keyword">var</span> done = <span class="hljs-literal">false</span>;<br><br><span class="hljs-comment">// 只执行一次的回调函数</span><br><span class="hljs-keyword">var</span> init = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{<br><span class="hljs-keyword">if</span> (!done) {<br>done = <span class="hljs-literal">true</span>;<br>fn();<br>}<br>}<br><br>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{<br><span class="hljs-keyword">try</span> {<br><span class="hljs-comment">// dom树未创建之前,调用doScroll的方法会报错</span><br>d.documentElement.doScroll(<span class="hljs-string">'left'</span>);<br>} <span class="hljs-keyword">catch</span> (e) {<br><span class="hljs-comment">//TODO handle the exception</span><br><span class="hljs-comment">// 延时再试一次</span><br><span class="hljs-comment">// arguments.callee 完成递归方法</span><br><span class="hljs-built_in">setTimeout</span>(<span class="hljs-built_in">arguments</span>.callee, <span class="hljs-number">50</span>);<br><span class="hljs-keyword">return</span>;<br>}<br><span class="hljs-comment">// 没有错误表示dom树创建完毕</span><br>init();<br>})();<br><br><span class="hljs-comment">// 监听document的加载状态</span><br>d.onreadystatechange = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{<br><span class="hljs-comment">// 如果用户在ready之后绑定的函数,则立马执行</span><br><span class="hljs-keyword">if</span> (d.readyState == <span class="hljs-string">'complete'</span>) {<br>d.onratechange = <span class="hljs-literal">null</span>;<br><br>init();<br>}<br>}<br>}<br>}<br></code></pre></td></tr></table></figure><p><img src="image_3.png" alt="image_3.png"></p><p>各主流框架DOMReady实现:<a href="https://www.cnblogs.com/JulyZhang/archive/2011/02/12/1952484.html">https://www.cnblogs.com/JulyZhang/archive/2011/02/12/1952484.html</a></p><p><span style="color: lightgray;"><em>未完待续</em></span></p>]]></content>
<categories>
<category>Web</category>
</categories>
<tags>
<tag>学习日记</tag>
<tag>Web</tag>
</tags>
</entry>
<entry>
<title>前端学习日记-log3</title>
<link href="/2019/05/10/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log3/"/>
<url>/2019/05/10/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log3/</url>
<content type="html"><![CDATA[<blockquote><p><em>继续上次的地方继续往下学习</em></p></blockquote><hr><h2 id="日志随笔"><a href="#日志随笔" class="headerlink" title="日志随笔"></a>日志随笔</h2><h3 id="1-DOM热身案例——滑动门特效"><a href="#1-DOM热身案例——滑动门特效" class="headerlink" title="1. DOM热身案例——滑动门特效"></a>1. <code>DOM</code>热身案例——滑动门特效</h3><p>代码已贴在上一篇文章里面,其中<code>js</code>中有个设置<code>onmouseover</code>的方法的逻辑,慕课网视频讲解中使用的是<code>js</code>的闭包函数循环设置的,可以参考注释掉的方法二,作为原生开发人员,我一开始不太理解这个闭包函数,认为可能会导致内存释放问题,这个疑问我先不去考虑了,先当做固定写法来使用,后面其他<code>js</code>课程再仔细理解</p><h3 id="2-了解DOM"><a href="#2-了解DOM" class="headerlink" title="2. 了解DOM"></a>2. 了解<code>DOM</code></h3><p><code>Document Object Model</code>文档对象模型,关键是理清标签节点</p><p><img src="image_1.png" alt="image_1.png"></p><p>W3C万维网联盟</p><p>元素节点、属性节点、文本节点、文档节点、文档片段节点</p><h3 id="3-文档片段节点"><a href="#3-文档片段节点" class="headerlink" title="3. 文档片段节点"></a>3. 文档片段节点</h3><p><code>createDocumentFragment</code>方法创建文档片段节点,这个节点加入到文档中不会显示出来,属于占位用的</p><h3 id="4-DOM的相关方法和属性"><a href="#4-DOM的相关方法和属性" class="headerlink" title="4. DOM的相关方法和属性"></a>4. <code>DOM</code>的相关方法和属性</h3><ul><li><p><code>nodeType</code>节点类型</p></li><li><p><code>nodeName</code>节点名称</p></li><li><p><code>nodeValue</code>节点值</p></li><li><p><code>attributes</code>属性节点数组</p></li><li><p><code>childNodes</code>子节点数组</p></li><li><p>文本节点<code>#text</code></p></li><li><p>注释节点<code>#comment</code></p></li><li><p>空节点</p></li><li><p><code>doctype</code></p></li><li><p>文档片段节点<code>#document-fragment</code></p></li></ul><p><img src="image_2.png" alt="image_2.png"></p><p><img src="image_3.png" alt="image_3.png"></p><p><span style="color: lightgray;"><em>未完待续</em></span></p>]]></content>
<categories>
<category>Web</category>
</categories>
<tags>
<tag>学习日记</tag>
<tag>Web</tag>
</tags>
</entry>
<entry>
<title>前端学习日记-log2</title>
<link href="/2019/04/24/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log2/"/>
<url>/2019/04/24/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log2/</url>
<content type="html"><![CDATA[<blockquote><p><em>继续上次的地方继续往下学习</em></p></blockquote><hr><h2 id="日志随笔"><a href="#日志随笔" class="headerlink" title="日志随笔"></a>日志随笔</h2><h3 id="8-单位"><a href="#8-单位" class="headerlink" title="8. 单位"></a>8. 单位</h3><ul><li><code>px</code>:像素</li></ul><p>我们用的最多的就是像素,一般移动端切图什么的都是使用像素作为单位,原生开发也一样</p><ul><li><p><code>em</code>:倍数</p></li><li><p>百分号:百分比</p></li></ul><h3 id="9-水平居中和垂直居中"><a href="#9-水平居中和垂直居中" class="headerlink" title="9. 水平居中和垂直居中"></a>9. 水平居中和垂直居中</h3><p>可以看教程,也可以自己理解,毕竟前面已经看了很多概念了</p><hr><blockquote><p><em><a href="https://www.imooc.com/">慕课网</a>上第二篇课程<a href="https://www.imooc.com/learn/36">JavaScript入门篇</a></em></p></blockquote><hr><h2 id="日志随笔-1"><a href="#日志随笔-1" class="headerlink" title="日志随笔"></a>日志随笔</h2><h3 id="1-引用js"><a href="#1-引用js" class="headerlink" title="1. 引用js"></a>1. 引用<code>js</code></h3><p><code>javascript</code>作为一种脚本语言可以放在<code>html</code>页面中任何位置,但是浏览器解释<code>html</code>时是按先后顺序的,所以前面的就先被执行。比如进行页面显示初始化的<code>js</code>必须放在<code>head</code>里面,因为初始化都要求提前进行(如给页面<code>body</code>设置<code>css</code>等);而如果是通过事件调用执行的<code>function</code>那么对位置没什么要求的</p><h3 id="2-变量和数据类型,这点w3school上讲的更清楚"><a href="#2-变量和数据类型,这点w3school上讲的更清楚" class="headerlink" title="2. 变量和数据类型,这点w3school上讲的更清楚"></a>2. 变量和数据类型,这点<a href="http://www.w3school.com.cn/js/js_datatypes.asp"><code>w3school</code></a>上讲的更清楚</h3><p><code>JavaScript</code>拥有动态类型,这点和<code>OC</code>很不一样,类型错误是没有提示的,要自己去排查。</p><p>布尔值、数组、字典写法差不多</p><p><code>Undefined</code>和<code>Null</code>,<code>Undefined</code>这个值表示变量不含有值,可以通过将变量的值设置为<code>null</code>来清空变量</p><h3 id="3-对象"><a href="#3-对象" class="headerlink" title="3. 对象"></a>3. 对象</h3><p><code>JavaScript</code>中的所有事物都是对象:字符串、数字、数组、日期,等等,对象是拥有属性和方法的数据</p><h3 id="4-函数方法"><a href="#4-函数方法" class="headerlink" title="4. 函数方法"></a>4. 函数方法</h3><p>方法使用及作用域基本一致,写法稍有区别,其他一些循环语句等设计都是一样的</p><h3 id="5-各种弹出窗口"><a href="#5-各种弹出窗口" class="headerlink" title="5. 各种弹出窗口"></a>5. 各种弹出窗口</h3><p><code>alert</code>、<code>confirm</code>、<code>prompt</code>都是原生系统浏览器对<code>html</code>的支持,其他window的方法也是<code>window.open</code>,<code>window.close</code></p><p><code>window</code>层的方法也是对原生容器开放的,原生可以直接触发,参考我的其他文章</p><hr><blockquote><p><em><a href="https://www.imooc.com/learn/488">DOM探索之基础详解篇</a></em></p></blockquote><hr><h3 id="1-DOM热身案例——滑动门特效"><a href="#1-DOM热身案例——滑动门特效" class="headerlink" title="1. DOM热身案例——滑动门特效"></a>1. <code>DOM</code>热身案例——滑动门特效</h3><figure class="highlight xml"><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><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment"><!-- html --></span><br><span class="hljs-meta"><!DOCTYPE <span class="hljs-meta-keyword">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">title</span>></span><span class="hljs-tag"></<span class="hljs-name">title</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"css/test1.css"</span> /></span><br><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"js/test1.js"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span><br><span class="hljs-tag"></<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">body</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"container"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"image1"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"size"</span>></span><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"image2"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"size"</span>></span><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"image3"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"size"</span>></span><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"image4"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"size"</span>></span><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">body</span>></span><br><span class="hljs-tag"></<span class="hljs-name">html</span>></span><br></code></pre></td></tr></table></figure><figure class="highlight awk"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><code class="hljs awk"><span class="hljs-regexp">//</span> test1.js<br>window.onload = <span class="hljs-keyword">function</span>() {<br><span class="hljs-regexp">//</span>获取image数组<br>var container = document.getElementById(<span class="hljs-string">"container"</span>);<br>var imgs = container.getElementsByTagName(<span class="hljs-string">"div"</span>);<br><br><span class="hljs-regexp">//</span>图片宽度<br>var imageWidth = imgs[<span class="hljs-number">0</span>].offsetWidth;<br><br><span class="hljs-regexp">//</span>设置边缘露出的堆叠宽度<br>var gapWidth = <span class="hljs-number">30</span>;<br><br><span class="hljs-regexp">//</span>整个容器宽度<br>var containerWidth = imageWidth + (imgs.length - <span class="hljs-number">1</span>) * gapWidth;<br>container.style.width = containerWidth + <span class="hljs-string">'px'</span>;<br><br><span class="hljs-regexp">//</span>初始位置<br><span class="hljs-keyword">function</span> setImgsPos() {<br><span class="hljs-keyword">for</span> (var i = <span class="hljs-number">1</span>; i < imgs.length; i++) {<br>imgs[i].style.left = imageWidth + gapWidth * (i - <span class="hljs-number">1</span>) + <span class="hljs-string">'px'</span>;<br>}<br>}<br>setImgsPos();<br><br><span class="hljs-regexp">//</span>左侧距离<br>var leftGap = imageWidth - gapWidth;<br><br><span class="hljs-regexp">//</span>设置四张图片的鼠标焦点方法<br>imgs[<span class="hljs-number">0</span>].onmouseover = <span class="hljs-keyword">function</span>() {<br>setImgsPos();<br>}<br>imgs[<span class="hljs-number">1</span>].onmouseover = <span class="hljs-keyword">function</span>() {<br>setImgsPos();<br>imgs[<span class="hljs-number">1</span>].style.left = gapWidth + <span class="hljs-string">'px'</span>;<br>parseInt()<br>}<br>imgs[<span class="hljs-number">2</span>].onmouseover = <span class="hljs-keyword">function</span>() {<br>setImgsPos();<br>imgs[<span class="hljs-number">1</span>].style.left = gapWidth + <span class="hljs-string">'px'</span>;<br>imgs[<span class="hljs-number">2</span>].style.left = gapWidth * <span class="hljs-number">2</span> + <span class="hljs-string">'px'</span>;<br>}<br>imgs[<span class="hljs-number">3</span>].onmouseover = <span class="hljs-keyword">function</span>() {<br>setImgsPos();<br>imgs[<span class="hljs-number">1</span>].style.left = gapWidth + <span class="hljs-string">'px'</span>;<br>imgs[<span class="hljs-number">2</span>].style.left = gapWidth * <span class="hljs-number">2</span> + <span class="hljs-string">'px'</span>;<br>imgs[<span class="hljs-number">3</span>].style.left = gapWidth * <span class="hljs-number">3</span> + <span class="hljs-string">'px'</span>;<br>}<br><br><span class="hljs-regexp">//</span>方法二,使用闭包设置四张图片的鼠标焦点方法<br><span class="hljs-regexp">//</span> <span class="hljs-keyword">for</span> (var i = <span class="hljs-number">0</span>; i < imgs.length; i++) {<br><span class="hljs-regexp">//</span> (<span class="hljs-keyword">function</span>(i) {<br><span class="hljs-regexp">//</span> imgs[i].onmouseover = <span class="hljs-keyword">function</span>() {<br><span class="hljs-regexp">//</span> setImgsPos();<br><span class="hljs-regexp">//</span> <br><span class="hljs-regexp">//</span> <span class="hljs-keyword">for</span> (var j = <span class="hljs-number">1</span>; j <= i; j++) {<br><span class="hljs-regexp">//</span> imgs[j].style.left = gapWidth * j + <span class="hljs-string">'px'</span>;<br><span class="hljs-regexp">//</span> }<br><span class="hljs-regexp">//</span> }<br><span class="hljs-regexp">//</span> })(i)<br><span class="hljs-regexp">//</span> }<br>};<br><br></code></pre></td></tr></table></figure><figure class="highlight css"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><code class="hljs css"><span class="hljs-comment">/* test1.css */</span><br><span class="hljs-selector-id">#container</span> {<br><span class="hljs-attribute">height</span>: <span class="hljs-number">300px</span>;<br><span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span> auto;<br><span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid red;<br><span class="hljs-attribute">overflow</span>: hidden;<br><span class="hljs-attribute">position</span>: relative;<br>}<br><br><span class="hljs-selector-class">.size</span> {<br><span class="hljs-attribute">width</span>: <span class="hljs-number">100px</span>;<br><span class="hljs-attribute">height</span>: <span class="hljs-number">100px</span>;<br><span class="hljs-attribute">position</span>: absolute;<br><span class="hljs-attribute">display</span>: block;<br><span class="hljs-attribute">left</span>: <span class="hljs-number">0</span>;<br>}<br><br><span class="hljs-selector-id">#image1</span> {<br><span class="hljs-attribute">background-color</span>: lightgray;<br>}<br><br><span class="hljs-selector-id">#image2</span> {<br><span class="hljs-attribute">background-color</span>: darkgray;<br>}<br><br><span class="hljs-selector-id">#image3</span> {<br><span class="hljs-attribute">background-color</span>: gray;<br>}<br><br><span class="hljs-selector-id">#image4</span> {<br><span class="hljs-attribute">background-color</span>: black;<br>}<br><br></code></pre></td></tr></table></figure><p><span style="color: lightgray;"><em>未完待续</em></span></p>]]></content>
<categories>
<category>Web</category>
</categories>
<tags>
<tag>学习日记</tag>
<tag>Web</tag>
</tags>
</entry>
<entry>
<title>前端学习日记-log1</title>
<link href="/2019/04/19/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log1/"/>
<url>/2019/04/19/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E6%97%A5%E8%AE%B0-log1/</url>
<content type="html"><![CDATA[<blockquote><p><em>现在网上有很多学习编程的网站和资料,例如<a href="http://www.w3school.com.cn/index.html">W3school</a>、<a href="http://www.runoob.com/">菜鸟教程</a>,我选择的是<a href="https://www.imooc.com/">慕课网</a></em></p></blockquote><blockquote><p><em>我决定先从<code>html</code>基础开始,免费课程:<a href="https://www.imooc.com/learn/9">初识HTML+CSS</a></em></p></blockquote><hr><h3 id="日志随笔"><a href="#日志随笔" class="headerlink" title="日志随笔"></a>日志随笔</h3><h5 id="1-html基础的标签知识"><a href="#1-html基础的标签知识" class="headerlink" title="1. html基础的标签知识"></a>1. <code>html</code>基础的标签知识</h5><p>基础的标签其实大学里面都学习过了,复习一下</p><h5 id="2-css样式属性"><a href="#2-css样式属性" class="headerlink" title="2. css样式属性"></a>2. <code>css</code>样式属性</h5><p>内联、嵌入、外部三种写法,优先级:内联>嵌入>外部</p><h5 id="3-css调用,标签选择、类选择、ID选择、子选择等"><a href="#3-css调用,标签选择、类选择、ID选择、子选择等" class="headerlink" title="3. css调用,标签选择、类选择、ID选择、子选择等"></a>3. <code>css</code>调用,标签选择、类选择、ID选择、子选择等</h5><p>熟练调用,合并相同属性,简化写法</p><h5 id="4-元素分类,盒子模型"><a href="#4-元素分类,盒子模型" class="headerlink" title="4. 元素分类,盒子模型"></a>4. 元素分类,盒子模型</h5><p>块状元素、内联元素(行内元素)、内联块状元素</p><p>常用的块状元素:<code><div>、<p>、<h1>...<h6>、<ol>、<ul>、<dl>、<table>、<address>、<blockquote> 、<form></code></p><p>常用的内联元素:<code><a>、<span>、<br>、<i>、<em>、<strong>、<label>、<q>、<var>、<cite>、<code></code></p><p>常用的内联块状元素:<code><img>、<input></code></p><h5 id="5-盒子模型"><a href="#5-盒子模型" class="headerlink" title="5. 盒子模型"></a>5. 盒子模型</h5><p>盒子模型:<code>margin、border、padding</code></p><h5 id="6-css布局模型"><a href="#6-css布局模型" class="headerlink" title="6. css布局模型"></a><span style="color: red;">6. <code>css</code>布局模型</span></h5><ul><li>流动模型</li></ul><p>流动(<code>Flow</code>)是默认的网页布局模式,也就是说网页在默认状态下的<code>HTML</code>网页元素都是根据流动模型来分布网页内容的。</p><p>典型的特征:</p><p>第一点,块状元素都会在所处的包含元素内自上而下按顺序垂直延伸分布,因为在默认状态下,块状元素的宽度都为100%。实际上,块状元素都会以行的形式占据位置。如右侧代码编辑器中三个块状元素标签<code>(div,h1,p)</code>宽度显示为100%。</p><p>第二点,在流动模型下,内联元素都会在所处的包含元素内从左到右水平分布显示。(内联元素可不像块状元素这么霸道独占一行)</p><ul><li>浮动模型</li></ul><p>任何元素在默认情况下是不能浮动的,但可以用<code>css</code>定义为浮动,如<code>div、p、table、img</code>等元素都可以被定义为浮动。</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs css"><span class="hljs-attribute">float</span><span class="hljs-selector-pseudo">:left</span>;<br><span class="hljs-attribute">float</span><span class="hljs-selector-pseudo">:right</span>;<br></code></pre></td></tr></table></figure><h5 id="7-层模型"><a href="#7-层模型" class="headerlink" title="7. 层模型"></a><span style="color: red;">7. 层模型</span></h5><p>层布局模型就像是图像软件PhotoShop中非常流行的图层编辑功能一样,每个图层能够精确定位操作</p><ul><li>绝对定位<code>(position: absolute)</code></li></ul><p>这条语句的作用将元素从文档流中拖出来,然后使用<code>left、right、top、bottom</code>属性相对于其最接近的一个具有定位属性的父包含块进行绝对定位。如果不存在这样的包含块,则相对于<code>body</code>元素,即相对于浏览器窗口。</p><ul><li>相对定位<code>(position: relative)</code></li></ul><p>相对定位完成的过程是首先按<code>static(float)</code>方式生成一个元素(并且元素像层一样浮动了起来),然后相对于以前的位置移动,移动的方向和幅度由<code>left、right、top、bottom</code>属性确定,偏移前的位置保留不动。</p><ul><li>固定定位<code>(position: fixed)</code></li></ul><p>由于视图本身是固定的,它不会随浏览器窗口的滚动条滚动而变化,除非你在屏幕中移动浏览器窗口的屏幕位置,或改变浏览器窗口的显示大小,因此固定定位的元素会始终位于浏览器窗口内视图的某个位置,不会受文档流动影响</p><p>练习:box4在box3标签内,把box4定位到box3的底部。</p><p>代码如下,通过相对定位<code>(position: relative)</code>和绝对定位<code>(position: absolute)</code>配合达到效果</p><figure class="highlight xml"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta"><!DOCTYPE <span class="hljs-meta-keyword">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">html</span>></span><br><span class="hljs-tag"><<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /></span><br><span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">title</span>></span><span class="hljs-tag"></<span class="hljs-name">title</span>></span><br><br><span class="hljs-tag"><<span class="hljs-name">style</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span>></span><br>#box3 {<br><span class="css"><span class="hljs-attribute">width</span>: <span class="hljs-number">200px</span>;</span><br><span class="css"><span class="hljs-attribute">height</span>: <span class="hljs-number">200px</span>;</span><br><span class="css"><span class="hljs-attribute">background-color</span>: red;</span><br><span class="css"><span class="hljs-attribute">position</span>: relative;</span><br>}<br>#box4 {<br><span class="css"><span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid black;</span><br><span class="css"><span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;</span><br><span class="css"><span class="hljs-attribute">position</span>: absolute;</span><br><span class="css"><span class="hljs-attribute">bottom</span>: <span class="hljs-number">0</span>;</span><br>}<br><span class="hljs-tag"></<span class="hljs-name">style</span>></span><br><span class="hljs-tag"></<span class="hljs-name">head</span>></span><br><span class="hljs-tag"><<span class="hljs-name">body</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"box3"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"box4"</span>></span>测试文字<span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">body</span>></span><br><span class="hljs-tag"></<span class="hljs-name">html</span>></span><br><br></code></pre></td></tr></table></figure><p><span style="color: lightgray;"><em>未完待续</em></span></p>]]></content>
<categories>
<category>Web</category>
</categories>
<tags>
<tag>学习日记</tag>
<tag>Web</tag>
</tags>
</entry>
<entry>
<title>前端学习计划</title>
<link href="/2019/04/15/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E8%AE%A1%E5%88%92/"/>
<url>/2019/04/15/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0%E8%AE%A1%E5%88%92/</url>
<content type="html"><![CDATA[<h4 id="一、目前现状"><a href="#一、目前现状" class="headerlink" title="一、目前现状"></a>一、目前现状</h4><p>我目前是iOS原生的开发人员,随着新技术的不断发展,我渐渐感觉到原生开发已无大的发展了,现在混合开发,跨平台前端开发才是主流。</p><p>现在移动端主要是iOS系统和Android系统的天下,作为系统的开发厂商,一定是希望使用系统自己的语言,直接使用系统提供的API来实现功能,但是这样开发工作量都是双份的,做一个功能,要用两种语言实现后分别,而且受限于各自系统不同的风格,出来的交互效果也会有所差距。</p><p>最近几年,随着芯片制造等技术的发展,智能手机的性能开始越来越高,普通的非游戏类app正常情况下不会有占用内存过多或者CPU的性能问题了。</p><p>随着这几年html5规范的制定完成,前端跨平台开发成为了可能,硬件的优化,语言的更新,使用html5开发的混合web app不在有性能的问题。</p><p>钉钉OA、微信小程序、企业微信等这些产品的发布,更加需要我们去做到一套代码,多平台适配,由此可见,前端时代已经到来。</p><h4 id="二、混合开发"><a href="#二、混合开发" class="headerlink" title="二、混合开发"></a>二、混合开发</h4><p>混合开发模式就是原生提供web容器,容器中加载h5页面,h5实现不了的一些方法,通过约定的交互方式由原生容器协助触发。例如页面跳转,原生一般都会使用系统提供的控制器实现页面跳转,这样用户体验比较真实,符合日常习惯,但是h5只有a标签的页面内重定向跳转,为了使web跳转更像原生APP的交互,可以约定调用方法,使得h5中也能使用原生的容器跳转,这样实现的效果比较好。</p><p>混合开发要求原生与h5约定一套交互方式,典型的有钉钉OA、企业微信,这两个app平台都是使用的这种方案,当然,各家有各家的方法。</p><h4 id="三、第三方开发打包工具"><a href="#三、第三方开发打包工具" class="headerlink" title="三、第三方开发打包工具"></a>三、第三方开发打包工具</h4><p>除了自己开发原生容器,当然还有一些大公司提供的标准打包平台的方案,例如React Native、WEEX和最近刚出的Flutter,都是大厂出产的前端开发app的工具,基本上可以说脱离了原生人员的参与。</p><h4 id="四、一些想法"><a href="#四、一些想法" class="headerlink" title="四、一些想法"></a>四、一些想法</h4><p>从技术角度来分析,未来的趋势几乎一定是跨平台的大前端时代,但是原生开发也不会被完全取代,毕竟移动端的硬件对接的还是iOS和Android的底层系统,但是,作为个人来讲,我现在要做,就是从现在开始转前端开发,为未来做好准备。</p>]]></content>
<categories>
<category>Web</category>
</categories>
<tags>
<tag>学习日记</tag>
<tag>Web</tag>
</tags>
</entry>
<entry>
<title>如何在macOS系统下搭建hexo博客</title>
<link href="/2019/04/11/%E5%A6%82%E4%BD%95%E5%9C%A8macOS%E7%B3%BB%E7%BB%9F%E4%B8%8B%E6%90%AD%E5%BB%BAhexo%E5%8D%9A%E5%AE%A2/"/>
<url>/2019/04/11/%E5%A6%82%E4%BD%95%E5%9C%A8macOS%E7%B3%BB%E7%BB%9F%E4%B8%8B%E6%90%AD%E5%BB%BAhexo%E5%8D%9A%E5%AE%A2/</url>
<content type="html"><![CDATA[<p><code>JavaScript</code>作为一种脚本语言,出现没多久就事实上统一了前端开发,而<code>Node.js</code>的出现,把<code>JavaScript</code>也带入到了后端服务的开发,<code>hexo</code>博客框架就是基于<code>node.js</code>开发的工具。</p><h4 id="一、安装node-js环境"><a href="#一、安装node-js环境" class="headerlink" title="一、安装node.js环境"></a>一、安装<code>node.js</code>环境</h4><p><code>node.js</code>有中文官网,地址:<a href="https://nodejs.org/zh-cn/">https://nodejs.org/zh-cn/</a>,<code>macOS</code>系统下直接下载安装包安装即可,官网建议使用<code>LTS</code>的稳定版本</p><p><img src="image_1.png" alt="image_1.png"></p><h4 id="二、node-js包管理工具npm"><a href="#二、node-js包管理工具npm" class="headerlink" title="二、node.js包管理工具npm"></a>二、<code>node.js</code>包管理工具<code>npm</code></h4><p>当越来越多的开发者使用<code>node.js</code>环境开发时,此时就需要一个统一管理这些开源包的工具,<code>npm</code>是世界上最大的软件注册表,基本上所有基于<code>node.js</code>的开源软件开发者都在使用<code>npm</code>互相分享,关于<code>npm</code>的介绍请参考<a href="https://www.npmjs.com.cn/">官网</a>,地址:<a href="https://www.npmjs.com.cn/">https://www.npmjs.com.cn/</a>。</p><p>而从刚才<code>node.js</code>官网中可以看到,我们安装的<code>node.js</code>安装包中已经包含了<code>npm</code>工具,可以直接开始使用。</p><h4 id="三、node-js版本管理工具Node-version-managers"><a href="#三、node-js版本管理工具Node-version-managers" class="headerlink" title="三、node.js版本管理工具Node version managers"></a>三、<code>node.js</code>版本管理工具<code>Node version managers</code></h4><p>一般情况下,我们安装完<code>node.js</code>后就可以直接使用了,但是会经常碰到一个权限的报错,官网也对这个问题进行了收录,地址:<a href="https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally">https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally</a>,官网给出了两个方法,推荐使用<code>Node version managers</code>重新安装<code>npm</code></p><p><code>Node version managers</code>简称<code>nvm</code>,就是用来管理<code>node.js</code>和<code>npm</code>的版本的,我们可以直接访问<code>github</code>上<code>manOS</code>版本的代码以及文档,地址:<a href="https://github.com/creationix/nvm">https://github.com/creationix/nvm</a>,根据文档说明使用如下命令行进行<code>nvm</code>的安装</p><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">$ curl -o- https:<span class="hljs-regexp">//</span>raw.githubusercontent.com<span class="hljs-regexp">/creationix/</span>nvm<span class="hljs-regexp">/v0.34.0/i</span>nstall.sh | bash<br></code></pre></td></tr></table></figure><p>注意:安装完之后,根据文档和终端弹出的提示,<code>nvm</code>启动需要如下的命令(不同的版本可能需要的命令有差别,请以终端弹出的提示为准)</p><figure class="highlight shell"><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><code class="hljs shell"><span class="hljs-meta">$</span><span class="bash"> <span class="hljs-built_in">export</span> NVM_DIR=<span class="hljs-string">"<span class="hljs-variable">$HOME</span>/.nvm"</span></span><br><span class="hljs-meta">$</span><span class="bash"> [ -s <span class="hljs-string">"<span class="hljs-variable">$NVM_DIR</span>/nvm.sh"</span> ] && \. <span class="hljs-string">"<span class="hljs-variable">$NVM_DIR</span>/nvm.sh"</span></span><br><br>//第三行命令是我的电脑上终端提示的,官方文档只有上面两条<br><span class="hljs-meta">$</span><span class="bash"> [ -s <span class="hljs-string">"<span class="hljs-variable">$NVM_DIR</span>/bash_completion"</span> ] && \. <span class="hljs-string">"<span class="hljs-variable">$NVM_DIR</span>/bash_completion"</span></span><br></code></pre></td></tr></table></figure><p>每次重启终端的,打开新的终端页面,都需要再次启动<code>nvm</code>命令,所以官方文档建议我们将命令配置到<code>nvm</code>的隐藏文件中,每次打开终端可以直接使用,我按照文档修改了<code>~/.bash_profile</code>文件,写入了以上的启动命令,保存后每次打开终端就可以直接使用<code>nvm</code>命令了。</p><p>安装完<code>nvm</code>后重新安装或更新<code>npm</code>,已经没有权限的报错了。</p><h4 id="四、淘宝镜像cnpm"><a href="#四、淘宝镜像cnpm" class="headerlink" title="四、淘宝镜像cnpm"></a>四、淘宝镜像<code>cnpm</code></h4><p>由于<code>npm</code>工具是国外的服务器,所以淘宝提供了一个国内的镜像版本,地址:<a href="https://npm.taobao.org/">https://npm.taobao.org/</a>,该网站上有使用文档,命令行简单引用即可,其他用法请自行参考。</p><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">$ npm install -g cnpm --registry=https:<span class="hljs-regexp">//</span>registry.npm.taobao.org<br></code></pre></td></tr></table></figure><h4 id="五、hexo博客框架搭建"><a href="#五、hexo博客框架搭建" class="headerlink" title="五、hexo博客框架搭建"></a>五、<code>hexo</code>博客框架搭建</h4><p>所有的环境安装结束后,开始生成<code>hexo</code>博客,<code>hexo</code>中文官网地址:<a href="https://hexo.io/zh-cn/">https://hexo.io/zh-cn/</a></p><h5 id="1-导入hexo代码"><a href="#1-导入hexo代码" class="headerlink" title="1. 导入hexo代码"></a>1. 导入<code>hexo</code>代码</h5><figure class="highlight avrasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs avrasm">$ npm install hexo-<span class="hljs-keyword">cli</span> -g<br></code></pre></td></tr></table></figure><p>注意:官网要求导入的是<code>hexo-cli</code>,而不是<code>hexo</code>,这两者是有区别的,<code>hexo-cli</code>负责使用<code>init</code>等命令创建<code>hexo</code>工程,创建好了之后,工程由<code>hexo</code>模块负责真正的项目工作(生成静态页面、预览等)。</p><h5 id="2-创建本地hexo工程"><a href="#2-创建本地hexo工程" class="headerlink" title="2. 创建本地hexo工程"></a>2. 创建本地<code>hexo</code>工程</h5><p>首先创建博客本地工程文件夹,我的文件夹名称就叫<code>MyBlog</code>,打开终端,<code>cd</code>命令到<code>MyBlog</code>文件夹后,使用<code>init</code>命令创建工程,当然也可以按照官网的命令行,效果一致。</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs csharp">$ hexo <span class="hljs-keyword">init</span><br></code></pre></td></tr></table></figure><p>等待<code>init</code>结束,<code>hexo</code>博客工程就已经创建好了</p><h5 id="3-hexo的常用命令"><a href="#3-hexo的常用命令" class="headerlink" title="3. hexo的常用命令"></a>3. <code>hexo</code>的常用命令</h5><figure class="highlight verilog"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs verilog"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 新建一篇markdown格式的文章</span><br><span class="hljs-comment"> 新建的文章目录是MyBlog/source/_posts</span><br><span class="hljs-comment"> */</span><br>$ hexo <span class="hljs-keyword">new</span> <title><br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 可直接缩写成首字母g,代表生成操作</span><br><span class="hljs-comment"> hexo框架会将本地的markdown文档和你的其他配置项生成一套完整的静态页面,页面生成路径为MyBlog/public子目录</span><br><span class="hljs-comment"> */</span><br>$ hexo <span class="hljs-keyword">generate</span><br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 可缩写成首字母d,代表将生成的静态网站页面部署到服务器上</span><br><span class="hljs-comment"> */</span><br>$ hexo deploy<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 可缩写成首字母s,代表使用本机预览生成好的网站</span><br><span class="hljs-comment"> 默认本机预览地址http://localhost:4000/</span><br><span class="hljs-comment"> */</span><br>$ hexo server<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> 清除缓存文件(db.json)和已生成的静态文件(public)</span><br><span class="hljs-comment"> 某些涉及网站、主题等的配置,可能需要执行clean命令重新生成</span><br><span class="hljs-comment"> */</span><br>$ hexo clean<br></code></pre></td></tr></table></figure><h4 id="六、关联Github"><a href="#六、关联Github" class="headerlink" title="六、关联Github"></a>六、关联<code>Github</code></h4><p>创建<code>github</code>账号,新建仓库,仓库名称写法为固定写法<code>用户名.github.io</code>,例如我的博客名称<code>AnderGH.github.io</code></p><p><img src="image_2.png" alt="image_2.png"></p><p>将完整的仓库地址配置在博客配置文件<code>_config.yml</code></p><p><img src="image_3.png" alt="image_3.png"></p><h4 id="七、其他问题"><a href="#七、其他问题" class="headerlink" title="七、其他问题"></a>七、其他问题</h4><ul><li>执行<code>hexo g</code>后报错</li></ul><blockquote><p>ERROR Deployer not found: git</p></blockquote><p>根据官方文档知道<code>hexo</code>框架升级到<code>3.0</code>版本之后需要安装<code>git</code>环境,如下命令</p><figure class="highlight ada"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ada">$ npm install hexo-deployer-git <span class="hljs-comment">--save</span><br></code></pre></td></tr></table></figure>]]></content>
<categories>
<category>Hexo</category>
</categories>
<tags>
<tag>Hexo</tag>
</tags>
</entry>
<entry>
<title>代码高亮</title>
<link href="/2019/04/01/%E4%BB%A3%E7%A0%81%E9%AB%98%E4%BA%AE/"/>
<url>/2019/04/01/%E4%BB%A3%E7%A0%81%E9%AB%98%E4%BA%AE/</url>
<content type="html"><![CDATA[<p>我的博客用的是<a href="http://forsigner.com/2016/03/10/fexo-doc-zh-cn/"><code>fexo</code></a>的主题,其中代码部分的显示效果一般,为了解决博文中代码部分高亮的问题,我准备集成<a href="https://highlightjs.org/"><code>highlight.js</code></a>的开源工具,官网地址:<a href="https://highlightjs.org/">https://highlightjs.org/</a></p><p><img src="image_1.png" alt="image_1"></p><h3 id="一、highlight-js集成"><a href="#一、highlight-js集成" class="headerlink" title="一、highlight.js集成"></a>一、<code>highlight.js</code>集成</h3><p><code>highlight.js</code>的集成非常简单,而且目前已经支持了非常多的语言支持和样式。</p><h4 id="1、方法选择"><a href="#1、方法选择" class="headerlink" title="1、方法选择"></a>1、方法选择</h4><p>点击首页的<code>Get Version</code>按钮,可以看大官网提供了很多集成方式</p><ul><li>Hosted:直接集成官网提供的网络版本,有cdnjs、jsdelivr两种缓存模式</li><li>Custom package:选择所需要支持的语言对应的版本,下载后使用源码集成,一般我们直接下载Common的即可满足大部分面向对象的语言</li><li>Node.js:使用Node.js的npm工具集成</li><li>Source:github下载源码集成</li></ul><p>我采用了第二种,选中我需要的语言支持,下载<code>package</code>压缩包集成</p><h4 id="2、集成过程"><a href="#2、集成过程" class="headerlink" title="2、集成过程"></a>2、集成过程</h4><ol><li>首先关闭<code>hexo</code>博客自带的代码高亮,修改博客根目录下<code>_config.yml</code>配置文件,设置<code>highlight</code>选项为<code>false</code></li></ol><p><img src="image_2.png" alt="image_2"></p><p>由于是修改的<code>hexo</code>的配置文件,所以需要执行<code>clean</code>命令行方法</p><figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs elixir"><span class="hljs-variable">$ </span>hexo clean<br></code></pre></td></tr></table></figure><ol start="2"><li><p>将压缩包解压后得到的<code>highlight</code>文件夹放入<code>fexo</code>的主题的目录下,我是和其他<code>css</code>、<code>js</code>资源文件放在了一起</p></li><li><p>找到<code>fexo</code>主题注入<code>js</code>和<code>css</code>文件的地方,将官网提供的源码写入即可</p></li></ol><figure class="highlight xml"><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><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/highlight/styles/xcode.css"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/highlight/highlight.pack.js"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span><br><span class="hljs-tag"><<span class="hljs-name">script</span>></span>hljs.initHighlightingOnLoad();<span class="hljs-tag"></<span class="hljs-name">script</span>></span><br></code></pre></td></tr></table></figure><p>此处我使用的是官网提供的<code>xcode.css</code>的样式,此时调试即可查看到代码高亮以及背景的效果了。</p><h3 id="二、个性化"><a href="#二、个性化" class="headerlink" title="二、个性化"></a>二、个性化</h3><p>在下载的所有的<code>css</code>样式中,我所有的样式都试过了一遍,没有什么特别喜欢的,所以我准备仿照提供的样式文件,自己写一个样式。</p><figure class="highlight xml"><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><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/highlight/custom/xcode.css"</span>></span><br><span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/highlight/highlight.pack.js"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span><br><span class="hljs-tag"><<span class="hljs-name">script</span>></span>hljs.initHighlightingOnLoad();<span class="hljs-tag"></<span class="hljs-name">script</span>></span><br></code></pre></td></tr></table></figure><p>我拷贝一份<code>xcode.css</code>文件,另外存放一个目录,通过浏览器不断调试样式,修改到了最终的结果,集成后感到比较满意</p><h3 id="三、行号"><a href="#三、行号" class="headerlink" title="三、行号"></a>三、行号</h3><p><code>highlight.js</code>使用起来非常简单,但是有个问题,不支持行号显示,网上有一些人在<code>highlight.js</code>基础上个性化了一些版本,可以支持行号,由于我本身不喜欢行号,所以没有集成,感兴趣的推荐进一步集成<a href="https://github.com/wcoder/highlightjs-line-numbers.js"><code>highlightjs-line-numbers.js</code></a>框架,地址:<a href="https://github.com/wcoder/highlightjs-line-numbers.js">https://github.com/wcoder/highlightjs-line-numbers.js</a></p><h3 id="四、其他优化"><a href="#四、其他优化" class="headerlink" title="四、其他优化"></a>四、其他优化</h3><p>在完成<code>highlight.js</code>的集成后,我对<code>fexo</code>自带的<code><code></code>标签以及<code><a></code>标签的颜色也想进行个性化。</p><ol><li>首先,我仍然是使用开放的个性化配置文件进行样式覆盖,<code>fexo</code>主题已提供了个性化样式的入口<code>personal-style.css</code></li></ol><figure class="highlight xml"><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></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-comment"><!--标签增加属性--></span><br><span class="hljs-tag"><<span class="hljs-name">style</span>></span><br><br><span class="css"><span class="hljs-selector-class">.article-content</span> <span class="hljs-selector-tag">a</span> {</span><br><span class="css"> <span class="hljs-attribute">color</span>: <span class="hljs-number">#0366d6</span>;</span><br>}<br><br><span class="css"><span class="hljs-selector-tag">code</span> {</span><br><span class="css"> <span class="hljs-attribute">background</span>: <span class="hljs-number">#F4F4F5</span>;</span><br><span class="css"> <span class="hljs-attribute">font-family</span>: SFMono-Regular,Consolas,<span class="hljs-string">"Liberation Mono"</span>,Menlo,Courier,monospace;</span><br><span class="css"> <span class="hljs-attribute">font-size</span>: <span class="hljs-number">0.8em</span>;</span><br>}<br><br><span class="css"><span class="hljs-selector-tag">table</span>><span class="hljs-selector-tag">thead</span>><span class="hljs-selector-tag">tr</span>><span class="hljs-selector-tag">th</span>, <span class="hljs-selector-tag">table</span>><span class="hljs-selector-tag">thead</span>><span class="hljs-selector-tag">tr</span>><span class="hljs-selector-tag">td</span> {</span><br><span class="css"> <span class="hljs-attribute">border-bottom-width</span>: <span class="hljs-number">1px</span>;</span><br>}<br><br><span class="hljs-tag"></<span class="hljs-name">style</span>></span><br></code></pre></td></tr></table></figure><p>通过重写属性,使用<code><style></code>标签提高优先级,覆盖原属性,达到了我想要的效果</p><ol start="2"><li><p>但是仍然存在一个问题,当<code><code></code>标签和<code><a></code>标签同时使用时,<code><code></code>标签中的颜色会把<code><a></code>覆盖</p><ol><li><p>通过浏览器调试,发现<code><code></code>标签自带了一个颜色,层级比<code><a></code>高,所以无法通过重写样式属性的方式修改,必须要修改源码</p></li><li><p>首先我分析了<code>fexo</code>主题样式部分的代码,发现其所有样式都是通过多个<code>scss</code>编译成一个<code>css</code>的</p></li></ol><p> 关于<a href="http://sass.bootcss.com/docs/sass-reference/"><code>scss</code></a>,感兴趣的可以看下官网文档,地址:<a href="http://sass.bootcss.com/docs/sass-reference/">http://sass.bootcss.com/docs/sass-reference/</a></p><ol start="3"><li>通过浏览器修改样式标签,我修改了<code>fexo</code>的源码,最终得到了我想要的效果</li></ol><p> 其中<a href="https://ninghao.net/blog/4790">https://ninghao.net/blog/4790</a>此博客的文章给我提供了方法</p></li></ol><h3 id="五、附录"><a href="#五、附录" class="headerlink" title="五、附录"></a>五、附录</h3><p>使用浏览器修改<code>scss</code>样式的方法截图如下</p><p><img src="image_3.png" alt="image_3"></p>]]></content>
<categories>
<category>Hexo</category>
</categories>
<tags>
<tag>Hexo</tag>
</tags>
</entry>
<entry>
<title>CocoaPods安装记录</title>
<link href="/2019/03/29/CocoaPods%E5%AE%89%E8%A3%85%E8%AE%B0%E5%BD%95/"/>
<url>/2019/03/29/CocoaPods%E5%AE%89%E8%A3%85%E8%AE%B0%E5%BD%95/</url>
<content type="html"><![CDATA[<p><code>CocoaPods</code>是<code>iOS</code>开发进行依赖管理的工具,可以方便开发人员引用和更新<code>Github</code>上的开源代码,本次记录下安装<code>CocoaPods</code>时的过程和遇到的问题。</p><h3 id="一、Ruby环境"><a href="#一、Ruby环境" class="headerlink" title="一、Ruby环境"></a>一、<code>Ruby</code>环境</h3><h4 id="1、Ruby版本"><a href="#1、Ruby版本" class="headerlink" title="1、Ruby版本"></a>1、<code>Ruby</code>版本</h4><p><code>ruby</code>是一种脚本语言,<code>cocoapods</code>就是<code>ruby</code>语言编写的,所以要首先确认<code>ruby</code>环境,打开<code>macOS</code>系统的终端程序,使用以下命令行查看<code>ruby</code>版本</p><figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs elixir"><span class="hljs-variable">$ </span>ruby -v<br></code></pre></td></tr></table></figure><p>我的两台mac都装了同一个系统,输出结果如下:</p><figure class="highlight less"><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><code class="hljs less"><span class="hljs-comment">//MacBook Pro (Retina, 15-inch, Mid 2015)</span><br><span class="hljs-selector-tag">ruby</span> <span class="hljs-selector-tag">2</span><span class="hljs-selector-class">.2</span><span class="hljs-selector-class">.2p95</span> (<span class="hljs-number">2015</span>-<span class="hljs-number">04</span>-<span class="hljs-number">13</span> revision <span class="hljs-number">50295</span>) <span class="hljs-selector-attr">[x86_64-darwin14]</span><br><br><span class="hljs-comment">//MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)</span><br><span class="hljs-selector-tag">ruby</span> <span class="hljs-selector-tag">2</span><span class="hljs-selector-class">.3</span><span class="hljs-selector-class">.7p456</span> (<span class="hljs-number">2018</span>-<span class="hljs-number">03</span>-<span class="hljs-number">28</span> revision <span class="hljs-number">63024</span>) <span class="hljs-selector-attr">[universal.x86_64-darwin17]</span><br></code></pre></td></tr></table></figure><p>15款的<code>mac</code>是一次一次升级系统升上来的,17款的是全新系统自带的,虽然是同一个系统版本,但是看到<code>ruby</code>不一样,由此可见,每次升级系统时<code>ruby</code>环境并不会随之升级。</p><p>通常情况下系统自带的<code>ruby</code>环境可以直接安装<code>cocoapods</code>,如果觉得<code>ruby</code>环境过低,需要升级<code>ruby</code>环境,那么暴力一点,可以直接抹掉系统重新安装,当然,我们还可以使用正常的方法升级</p><h4 id="2、Ruby升级"><a href="#2、Ruby升级" class="headerlink" title="2、Ruby升级"></a>2、<code>Ruby</code>升级</h4><p><code>Ruby</code>环境有个工具叫版本管理器,英文<code>Ruby Version Manager</code>,简称<code>RVM</code>,主要就是用来管理<code>ruby</code>版本的,<code>macOS</code>系统没有自带这个工具,所以需要先安装此工具。</p><p><code>RVM</code>有官方网站<a href="https://www.rvm.io/">https://www.rvm.io/</a></p><ol><li>按照官方说明,首先需要安装<code>GPG</code>秘钥,<code>macOS</code>没有安装工具,所以不能直接安装秘钥</li></ol><p>安装<code>GPG</code>组件可以有两种安装方法</p><ul><li>使用<code>Homebrew</code>安装</li><li><code>GPG</code>官网<a href="https://gpgtools.org/">https://gpgtools.org/</a>已发布安装包,可以直接下载安装</li></ul><p>安装过程中可能出现报错,可以自行搜索解决,我是通过<code>vpn</code>下载了<code>GPG</code>官网的安装包,直接进行的安装,安装完成后根据提示设置即可</p><ol start="2"><li><code>GPG</code>安装成功后,再执行<code>RVM</code>官网提供的命令行,既可成功安装<code>rvm</code>工具</li></ol><p>请确保网络环境的正常访问,否则会安装失败,使用命令行查看<code>rvm</code>版本<code>rvm -v</code>,可确认是否安装成功</p><figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">rvm</span> <span class="hljs-number">1</span>.<span class="hljs-number">29</span>.<span class="hljs-number">7</span> (latest) by Michal Papis, Piotr Kuczynski, Wayne E. Seguin<span class="hljs-meta"> [https://rvm.io]</span><br></code></pre></td></tr></table></figure><ol start="3"><li>安装<code>ruby</code>新版本</li></ol><figure class="highlight scss"><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></pre></td><td class="code"><pre><code class="hljs scss"><span class="hljs-comment">//查看ruby所有版本</span><br>$ rvm list known<br><br># MRI Rubies<br><span class="hljs-selector-attr">[ruby-]</span>1<span class="hljs-selector-class">.8</span><span class="hljs-selector-class">.6</span><span class="hljs-selector-attr">[-p420]</span><br><span class="hljs-selector-attr">[ruby-]</span>1<span class="hljs-selector-class">.8</span><span class="hljs-selector-class">.7</span><span class="hljs-selector-attr">[-head]</span> # security released on head<br><span class="hljs-selector-attr">[ruby-]</span>1<span class="hljs-selector-class">.9</span><span class="hljs-selector-class">.1</span><span class="hljs-selector-attr">[-p431]</span><br><span class="hljs-selector-attr">[ruby-]</span>1<span class="hljs-selector-class">.9</span><span class="hljs-selector-class">.2</span><span class="hljs-selector-attr">[-p330]</span><br><span class="hljs-selector-attr">[ruby-]</span>1<span class="hljs-selector-class">.9</span><span class="hljs-selector-class">.3</span><span class="hljs-selector-attr">[-p551]</span><br><span class="hljs-selector-attr">[ruby-]</span>2<span class="hljs-selector-class">.0</span><span class="hljs-selector-class">.0</span><span class="hljs-selector-attr">[-p648]</span><br><span class="hljs-selector-attr">[ruby-]</span>2<span class="hljs-selector-class">.1</span><span class="hljs-selector-attr">[.8]</span><br><span class="hljs-selector-attr">[ruby-]</span>2<span class="hljs-selector-class">.2</span><span class="hljs-selector-attr">[.4]</span><br><span class="hljs-selector-attr">[ruby-]</span>2<span class="hljs-selector-class">.3</span><span class="hljs-selector-attr">[.0]</span><br><span class="hljs-selector-attr">[ruby-]</span>2<span class="hljs-selector-class">.2-head</span><br>ruby-head<br></code></pre></td></tr></table></figure><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs awk"><span class="hljs-regexp">//</span>安装<span class="hljs-number">2.3</span>.<span class="hljs-number">0</span>版本<br>$ rvm install <span class="hljs-number">2.3</span>.<span class="hljs-number">0</span><br></code></pre></td></tr></table></figure><figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs actionscript"><span class="hljs-comment">//设置为系统默认版本</span><br>$ rvm <span class="hljs-keyword">use</span> <span class="hljs-number">2.3</span><span class="hljs-number">.0</span> --<span class="hljs-keyword">default</span><br></code></pre></td></tr></table></figure><h3 id="二、安装CocoaPods环境"><a href="#二、安装CocoaPods环境" class="headerlink" title="二、安装CocoaPods环境"></a>二、安装<code>CocoaPods</code>环境</h3><p><code>RubyGems</code>,简称<code>gems</code>是一个用于对<code>Ruby</code>组件进行打包的<code>Ruby</code>打包系统。<code>macOS</code>系统已集成了<code>gem</code>环境。</p><h4 id="1、使用命令行安装cocoapods"><a href="#1、使用命令行安装cocoapods" class="headerlink" title="1、使用命令行安装cocoapods"></a>1、使用命令行安装<code>cocoapods</code></h4><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs cmake">$ sudo gem <span class="hljs-keyword">install</span> cocoapods<br></code></pre></td></tr></table></figure><h4 id="2、切换ruby软件源"><a href="#2、切换ruby软件源" class="headerlink" title="2、切换ruby软件源"></a>2、切换<code>ruby</code>软件源</h4><p><code>ruby</code>的默认软件源<a href="https://rubygems.org/">https://rubygems.org</a>,是亚马逊的服务,国内无法访问,需要切换为国内的镜像<a href="https://gems.ruby-china.com/">https://gems.ruby-china.com/</a>,按照镜像网站上的命令行切换即可</p><figure class="highlight vim"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs vim">$ gem sources --<span class="hljs-built_in">add</span> http<span class="hljs-variable">s:</span>//gems.<span class="hljs-keyword">ruby</span>-china.<span class="hljs-keyword">com</span>/ --<span class="hljs-built_in">remove</span> http<span class="hljs-variable">s:</span>//rubygems.org/<br></code></pre></td></tr></table></figure><figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs elixir"><span class="hljs-variable">$ </span>gem sources -l<br></code></pre></td></tr></table></figure><p>使用<code>-l</code>命令确保只有<code>gems.ruby-china.com</code>的软件源</p><figure class="highlight vim"><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><code class="hljs vim">*** CURRENT SOURCES ***<br><br>http<span class="hljs-variable">s:</span>//gems.<span class="hljs-keyword">ruby</span>-china.<span class="hljs-keyword">com</span>/<br></code></pre></td></tr></table></figure><h4 id="3、镜像索引替换"><a href="#3、镜像索引替换" class="headerlink" title="3、镜像索引替换"></a>3、镜像索引替换</h4><p><code>github</code>上所有的项目的<code>podspec</code>都保存在<a href="https://github.com/CocoaPods/Specs">https://github.com/CocoaPods/Specs.git</a>,我们需要把保存的所有索引下载到本地,这样才能在执行pod命令时正常获取到github上的资源路径,虽然索引信息不大,只有几百兆,但是由于数量很多,检索起来非常耗时,国内访问<code>github</code>速度非常慢,所以建议使用<a href="https://gitclub.cn/CocoaPods/Specs">https://gitclub.cn/CocoaPods/Specs.git</a>替换,如下:</p><ul><li>方法一:</li></ul><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">$ git clone https:<span class="hljs-regexp">//gi</span>tclub.cn<span class="hljs-regexp">/CocoaPods/</span>Specs.git ~<span class="hljs-regexp">/.cocoapods/</span>repos/master<br></code></pre></td></tr></table></figure><p>使用<code>git clone</code>方法拷贝到本地,后面的<code>~/.cocoapods/repos/master</code>目录是本地的目录,一般我们将<code>cocoapods</code>目录做成隐藏目录,并放在系统根目录下,目录结构<code>repos/master</code>,执行命令行时,会自动在根目录下创建<code>.cocoapods</code>的隐藏目录,使用终端工具可以查看到该隐藏目录。</p><div style="color: red">注意:此命令行较为耗时,请确保网络环境的顺畅,同时建议先排查本机环境配置,争取一次成功,常见报错及配置如下:</div><br/><blockquote><p>RPC failed; curl 56 LibreSSL SSL_read: SSL_ERROR_SYSCALL, errno</p></blockquote><p>此系列报错均可以通过配置解决,具体按<code>errno</code>后面的报错码决定,可依次检查以下配置:</p><ol><li>设置<code>postBuffer</code>值大一点,1048576000是1000M<figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs lua">$ git <span class="hljs-built_in">config</span> <span class="hljs-comment">--global http.postBuffer 1048576000</span><br></code></pre></td></tr></table></figure></li><li><code>Xcode</code>配置问题</li></ol><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs gradle">sudo xcode-select -<span class="hljs-keyword">switch</span> <span class="hljs-regexp">/Applications/</span>Xcode.app<span class="hljs-regexp">/Contents/</span>Developer<br></code></pre></td></tr></table></figure><p>根据你默认的<code>Xcode</code>来修改在<code>/Applications/和/Contents/Developer</code>中间的<code>app</code>的名字</p><ul><li>方法二:</li></ul><p>如果<code>git clone</code>的命令下载速度很慢,那么可以使用其他下载工具,直接下载<code>zip</code>格式或其他格式压缩包,<code>github</code>和<code>gitclub</code>都提供了压缩包的下载方式,使用第三方客户端下载会比较快速下载完之后,需要手动创建<code>.cocoapods</code>目录,并将压缩包解压后组成完成的目录<code>~/.cocoapods/repos/master</code></p><p><img src="image_1.png" alt="image_1.png"></p><h4 id="4、setup指令"><a href="#4、setup指令" class="headerlink" title="4、setup指令"></a>4、<code>setup</code>指令</h4><p><code>git</code>拷贝成功后,需要执行如下命令:</p><figure class="highlight arduino"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs arduino">$ pod setup<br></code></pre></td></tr></table></figure><p>继续等待一段时间后,<code>cocoapods</code>环境即全部安装成功,<div style="color: red">同样需要注意网络顺畅</div><br/></p><h3 id="三、pod版本修改"><a href="#三、pod版本修改" class="headerlink" title="三、pod版本修改"></a>三、pod版本修改</h3><p>不同版本的cocoapods在应用第三方代码时有不同的地方,有时会导致头文件报错,或者引用失败等情况,通过<code>--version</code>查看安装的pod版本</p><figure class="highlight ada"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ada">$ pod <span class="hljs-comment">--version</span><br></code></pre></td></tr></table></figure><p>上面安装时<code>install</code>命令没有指定版本号,所以默认安装的是最新的版本,通过<code>gem</code>命令查看所有的pod版本</p><figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs elixir"><span class="hljs-variable">$ </span>gem list<br></code></pre></td></tr></table></figure><p>如下:</p><figure class="highlight erlang"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><code class="hljs erlang">*** LOCAL GEMS ***<br><br><span class="hljs-function"><span class="hljs-title">activesupport</span> <span class="hljs-params">(<span class="hljs-number">4.2</span>.<span class="hljs-number">11.1</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">atomos</span> <span class="hljs-params">(<span class="hljs-number">0.1</span>.<span class="hljs-number">3</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">bigdecimal</span> <span class="hljs-params">(<span class="hljs-number">1.2</span>.<span class="hljs-number">8</span>)</span></span><br><span class="hljs-function">CFP<span class="hljs-title">ropertyList</span> <span class="hljs-params">(<span class="hljs-number">3.0</span>.<span class="hljs-number">0</span>, <span class="hljs-number">2.2</span>.<span class="hljs-number">8</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">claide</span> <span class="hljs-params">(<span class="hljs-number">1.0</span>.<span class="hljs-number">2</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">cocoapods</span> <span class="hljs-params">(<span class="hljs-number">1.6</span>.<span class="hljs-number">1</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">cocoapods</span>-<span class="hljs-title">core</span> <span class="hljs-params">(<span class="hljs-number">1.6</span>.<span class="hljs-number">1</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">cocoapods</span>-<span class="hljs-title">deintegrate</span> <span class="hljs-params">(<span class="hljs-number">1.0</span>.<span class="hljs-number">3</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">cocoapods</span>-<span class="hljs-title">downloader</span> <span class="hljs-params">(<span class="hljs-number">1.2</span>.<span class="hljs-number">2</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">cocoapods</span>-<span class="hljs-title">plugins</span> <span class="hljs-params">(<span class="hljs-number">1.0</span>.<span class="hljs-number">0</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">cocoapods</span>-<span class="hljs-title">search</span> <span class="hljs-params">(<span class="hljs-number">1.0</span>.<span class="hljs-number">0</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">cocoapods</span>-<span class="hljs-title">stats</span> <span class="hljs-params">(<span class="hljs-number">1.1</span>.<span class="hljs-number">0</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">cocoapods</span>-<span class="hljs-title">trunk</span> <span class="hljs-params">(<span class="hljs-number">1.6</span>.<span class="hljs-number">1</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">cocoapods</span>-<span class="hljs-title">try</span> <span class="hljs-params">(<span class="hljs-number">1.1</span>.<span class="hljs-number">0</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">colored2</span> <span class="hljs-params">(<span class="hljs-number">3.1</span>.<span class="hljs-number">2</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">concurrent</span>-<span class="hljs-title">ruby</span> <span class="hljs-params">(<span class="hljs-number">1.1</span>.<span class="hljs-number">5</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">did_you_mean</span> <span class="hljs-params">(<span class="hljs-number">1.0</span>.<span class="hljs-number">0</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">escape</span> <span class="hljs-params">(<span class="hljs-number">0.0</span>.<span class="hljs-number">4</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">fourflusher</span> <span class="hljs-params">(<span class="hljs-number">2.2</span>.<span class="hljs-number">0</span>, <span class="hljs-number">2.0</span>.<span class="hljs-number">1</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">fuzzy_match</span> <span class="hljs-params">(<span class="hljs-number">2.0</span>.<span class="hljs-number">4</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">gh_inspector</span> <span class="hljs-params">(<span class="hljs-number">1.1</span>.<span class="hljs-number">3</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">i18n</span> <span class="hljs-params">(<span class="hljs-number">0.9</span>.<span class="hljs-number">5</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">io</span>-<span class="hljs-title">console</span> <span class="hljs-params">(<span class="hljs-number">0.4</span>.<span class="hljs-number">5</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">json</span> <span class="hljs-params">(<span class="hljs-number">1.8</span>.<span class="hljs-number">3.1</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">libxml</span>-<span class="hljs-title">ruby</span> <span class="hljs-params">(<span class="hljs-number">2.9</span>.<span class="hljs-number">0</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">minitest</span> <span class="hljs-params">(<span class="hljs-number">5.8</span>.<span class="hljs-number">5</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">molinillo</span> <span class="hljs-params">(<span class="hljs-number">0.6</span>.<span class="hljs-number">6</span>, <span class="hljs-number">0.5</span>.<span class="hljs-number">7</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">nanaimo</span> <span class="hljs-params">(<span class="hljs-number">0.2</span>.<span class="hljs-number">6</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">nap</span> <span class="hljs-params">(<span class="hljs-number">1.1</span>.<span class="hljs-number">0</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">net</span>-<span class="hljs-title">telnet</span> <span class="hljs-params">(<span class="hljs-number">0.1</span>.<span class="hljs-number">1</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">netrc</span> <span class="hljs-params">(<span class="hljs-number">0.11</span>.<span class="hljs-number">0</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">nokogiri</span> <span class="hljs-params">(<span class="hljs-number">1.5</span>.<span class="hljs-number">6</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">power_assert</span> <span class="hljs-params">(<span class="hljs-number">0.2</span>.<span class="hljs-number">6</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">psych</span> <span class="hljs-params">(<span class="hljs-number">2.1</span>.<span class="hljs-number">0.1</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">rake</span> <span class="hljs-params">(<span class="hljs-number">10.4</span>.<span class="hljs-number">2</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">rdoc</span> <span class="hljs-params">(<span class="hljs-number">4.2</span>.<span class="hljs-number">1</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">ruby</span>-<span class="hljs-title">macho</span> <span class="hljs-params">(<span class="hljs-number">1.4</span>.<span class="hljs-number">0</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">sqlite3</span> <span class="hljs-params">(<span class="hljs-number">1.3</span>.<span class="hljs-number">11</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">test</span>-<span class="hljs-title">unit</span> <span class="hljs-params">(<span class="hljs-number">3.1</span>.<span class="hljs-number">5</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">thread_safe</span> <span class="hljs-params">(<span class="hljs-number">0.3</span>.<span class="hljs-number">6</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">tzinfo</span> <span class="hljs-params">(<span class="hljs-number">1.2</span>.<span class="hljs-number">5</span>)</span></span><br><span class="hljs-function"><span class="hljs-title">xcodeproj</span> <span class="hljs-params">(<span class="hljs-number">1.8</span>.<span class="hljs-number">1</span>)</span></span><br></code></pre></td></tr></table></figure><p>当前安装的为<code>cocoapods (1.6.1)</code>版本,我们要切换到1.3.1的版本,通过<code>uninstall</code>的命令即可实现</p><figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs elixir"><span class="hljs-variable">$ </span>gem uninstall cocoapods -v <span class="hljs-number">1.6</span>.<span class="hljs-number">1</span><br></code></pre></td></tr></table></figure><p>当移除最后一个版本时,会提示</p><figure class="highlight vim"><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><code class="hljs vim">Remove <span class="hljs-built_in">executable</span><span class="hljs-variable">s:</span><br>pod, <span class="hljs-keyword">sandbox</span>-pod<br><br>in addition <span class="hljs-keyword">to</span> the gem? [Yn]<br></code></pre></td></tr></table></figure><p>回车或者Y进行确认,删除<code>pod</code>目录,再安装执行版本即可</p><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs cmake">$ gem <span class="hljs-keyword">install</span> cocoapods -v <span class="hljs-number">1.3</span>.<span class="hljs-number">1</span><br></code></pre></td></tr></table></figure><p>注意:如果出现关于文件权限的报错问题,或者删除命令无效,可以使用<code>sudo</code>系统管理员的权限重复操作</p><h3 id="四、附录:"><a href="#四、附录:" class="headerlink" title="四、附录:"></a>四、附录:</h3><p>摘自<a href="https://kaqijiang.github.io/mac%E5%B7%A5%E5%85%B7/2018/03/09/Mac%E5%AE%89%E8%A3%85Ruby%E7%89%88%E6%9C%AC%E7%AE%A1%E7%90%86%E5%99%A8-RVM.html">https://kaqijiang.github.io/mac工具/2018/03/09/Mac安装Ruby版本管理器-RVM.html</a></p><ul><li><code>ruby</code>、<code>rvm</code>常用指令</li></ul><figure class="highlight powershell"><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></pre></td><td class="code"><pre><code class="hljs powershell"><span class="hljs-variable">$</span> ruby <span class="hljs-literal">-v</span> <span class="hljs-comment"># 查看ruby 版本</span><br><span class="hljs-variable">$</span> rvm list known <span class="hljs-comment"># 列出已知的 ruby 版本</span><br><span class="hljs-variable">$</span> rvm install <span class="hljs-number">2.3</span>.<span class="hljs-number">0</span> <span class="hljs-comment"># 选择指定 ruby 版本进行更新</span><br><span class="hljs-variable">$</span> rvm get stable <span class="hljs-comment"># 更新 rvm</span><br><span class="hljs-variable">$</span> rvm use <span class="hljs-number">2.2</span>.<span class="hljs-number">2</span> <span class="hljs-comment"># 切换到指定 ruby 版本</span><br><span class="hljs-variable">$</span> rvm use <span class="hljs-number">2.2</span>.<span class="hljs-number">2</span> -<span class="hljs-literal">-default</span> <span class="hljs-comment"># 设置指定 ruby 版本为默认版本</span><br><span class="hljs-variable">$</span> rvm list <span class="hljs-comment"># 查询已安装的 ruby 版本</span><br><span class="hljs-variable">$</span> rvm remove <span class="hljs-number">1.9</span>.<span class="hljs-number">2</span> <span class="hljs-comment"># 卸载移除 指定 ruby 版本</span><br><br><span class="hljs-variable">$</span> <span class="hljs-built_in">curl</span> <span class="hljs-literal">-L</span> https://get.rvm.io | bash <span class="hljs-literal">-s</span> stable <span class="hljs-comment"># 安装 rvm 环境</span><br><span class="hljs-variable">$</span> <span class="hljs-built_in">curl</span> <span class="hljs-literal">-sSL</span> https://get.rvm.io | bash <span class="hljs-literal">-s</span> stable -<span class="hljs-literal">-ruby</span> <span class="hljs-comment"># 默认安装 rvm 最新版本</span><br><span class="hljs-variable">$</span> <span class="hljs-built_in">curl</span> <span class="hljs-literal">-sSL</span> https://get.rvm.io | bash <span class="hljs-literal">-s</span> stable -<span class="hljs-literal">-ruby</span>=<span class="hljs-number">2.3</span>.<span class="hljs-number">0</span> <span class="hljs-comment"># 安装 rvm 指定版本</span><br><span class="hljs-variable">$</span> source ~/.rvm/scripts/rvm <span class="hljs-comment"># 载入 rvm</span><br></code></pre></td></tr></table></figure><ul><li><code>gem</code>常用指令</li></ul><figure class="highlight shell"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><code class="hljs shell"><span class="hljs-meta">$</span><span class="bash"> gem -v <span class="hljs-comment"># 查看 gem 版本</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem <span class="hljs-built_in">source</span> <span class="hljs-comment"># 查看 gem 配置源</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem <span class="hljs-built_in">source</span> -l <span class="hljs-comment"># 查看 gem 配置源目录</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem sources -a url <span class="hljs-comment"># 添加 gem 配置源(url 需换成网址)</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem sources --add url <span class="hljs-comment"># 添加 gem 配置源(url 需换成网址)</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem sources -r url <span class="hljs-comment"># 删除 gem 配置源(url 需换成网址)</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem sources --remove url <span class="hljs-comment"># 删除 gem 配置源(url 需换成网址)</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem update <span class="hljs-comment"># 更新 所有包</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem update --system <span class="hljs-comment"># 更新 Ruby Gems 软件</span></span><br><br><span class="hljs-meta">$</span><span class="bash"> gem install rake <span class="hljs-comment"># 安装 rake,从本地或远程服务器</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem install rake --remote <span class="hljs-comment"># 安装 rake,从远程服务器</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem install watir -v 1.6.2 <span class="hljs-comment"># 安装 指定版本的 watir</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem install watir --version 1.6.2 <span class="hljs-comment"># 安装 指定版本的 watir</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem uninstall rake <span class="hljs-comment"># 卸载 rake 包</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem list d <span class="hljs-comment"># 列出 本地以 d 打头的包</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem query -n <span class="hljs-string">''</span>[0-9]<span class="hljs-string">''</span> --<span class="hljs-built_in">local</span> <span class="hljs-comment"># 查找 本地含有数字的包</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem search <span class="hljs-built_in">log</span> --both <span class="hljs-comment"># 查找 从本地和远程服务器上查找含有 log 字符串的包</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem search <span class="hljs-built_in">log</span> --remoter <span class="hljs-comment"># 查找 只从远程服务器上查找含有 log 字符串的包</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem search -r <span class="hljs-built_in">log</span> <span class="hljs-comment"># 查找 只从远程服务器上查找含有log字符串的包</span></span><br><br><span class="hljs-meta">$</span><span class="bash"> gem <span class="hljs-built_in">help</span> <span class="hljs-comment"># 提醒式的帮助</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem <span class="hljs-built_in">help</span> install <span class="hljs-comment"># 列出 install 命令 帮助</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem <span class="hljs-built_in">help</span> examples <span class="hljs-comment"># 列出 gem 命令使用一些例子</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem build rake.gemspec <span class="hljs-comment"># 把 rake.gemspec 编译成 rake.gem</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem check -v pkg/rake-0.4.0.gem <span class="hljs-comment"># 检测 rake 是否有效</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem cleanup <span class="hljs-comment"># 清除 所有包旧版本,保留最新版本</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem contents rake <span class="hljs-comment"># 显示 rake 包中所包含的文件</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem dependency rails -v 0.10.1 <span class="hljs-comment"># 列出 与 rails 相互依赖的包</span></span><br><span class="hljs-meta">$</span><span class="bash"> gem environment <span class="hljs-comment"># 查看 gem 的环境</span></span><br><br><span class="hljs-meta">$</span><span class="bash"> sudo gem -v <span class="hljs-comment"># 查看 gem 版本(以管理员权限)</span></span><br><span class="hljs-meta">$</span><span class="bash"> sudo gem install cocoa pods <span class="hljs-comment"># 安装 CocoaPods(以管理员权限)</span></span><br><span class="hljs-meta">$</span><span class="bash"> sudo gem install cocoapods <span class="hljs-comment"># 安装 CocoaPods(以管理员权限)</span></span><br><span class="hljs-meta">$</span><span class="bash"> sudo gem install cocoapods --pre <span class="hljs-comment"># 安装 CocoaPods 至预览版(以管理员权限)</span></span><br><span class="hljs-meta">$</span><span class="bash"> sudo gem install cocoapods -v 0.39.0 <span class="hljs-comment"># 安装 CocoaPods 指定版本(以管理员权限)</span></span><br><span class="hljs-meta">$</span><span class="bash"> sudo gem update cocoapods <span class="hljs-comment"># 更新 CocoaPods 至最新版(以管理员权限)</span></span><br><span class="hljs-meta">$</span><span class="bash"> sudo gem update cocoapods --pre <span class="hljs-comment"># 更新 CocoaPods 至预览版(以管理员权限)</span></span><br><span class="hljs-meta">$</span><span class="bash"> sudo gem uninstall cocoapods -v 0.39.0 <span class="hljs-comment"># 移除 CocoaPods 指定版本(以管理员权限)</span></span><br></code></pre></td></tr></table></figure><ul><li><code>pod</code>常用指令</li></ul><figure class="highlight elixir"><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><code class="hljs elixir"><span class="hljs-variable">$ </span>pod setup <span class="hljs-comment"># CocoaPods 将信息下载到~/.cocoapods/repos 目录下。如果安装 CocoaPods 时不执行此命令,在初次执行 pod intall 命令时,系统也会自动执行该指令</span><br><span class="hljs-variable">$ </span>pod --version <span class="hljs-comment"># 检查 CocoaPods 是否安装成功及其版本号</span><br><span class="hljs-variable">$ </span>pod install <span class="hljs-comment"># 安装 CocoaPods 的配置文件 Podfile</span><br></code></pre></td></tr></table></figure>]]></content>
<categories>
<category>iOS</category>
</categories>
<tags>
<tag>iOS</tag>
<tag>CocoaPods</tag>
</tags>
</entry>
<entry>
<title>正则表达式快速入门</title>
<link href="/2019/03/29/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8/"/>
<url>/2019/03/29/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8/</url>
<content type="html"><![CDATA[<p>想要精通正则表达式,确实非常不容易,但是一般情况下,我们在项目中用到的正则表达式都是非常简单的。</p><p>构造正则表达式的方法和创建数学表达式的方法相似,就是用多种元素符与操作符将小的表达式结合在一起来创建更大的表达式。正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。元字符是组成正则表达式的最重要部分。</p><h3 id="一、核心的常用元字符"><a href="#一、核心的常用元字符" class="headerlink" title="一、核心的常用元字符"></a>一、核心的常用元字符</h3><p>完整的元字符表可以百度查询,此处只列举几个常见的快速入门的元字符</p><table><thead><tr><th>字符</th><th>描述</th></tr></thead><tbody><tr><td>abc</td><td>包含字符串<code>abc</code></td></tr><tr><td>^</td><td>开头的标识,<code>^abc</code>表示以字符串<code>abc</code>开头</td></tr><tr><td>$</td><td>结尾的标识,<code>abc$</code>表示以字符串<code>abc</code>结尾</td></tr><tr><td>{3,7}</td><td>字符连续出现最少3次,最多7次,<code>a{2,4}</code>表示<code>aa</code>、<code>aaa</code>、<code>aaaa</code>三种情况</td></tr><tr><td>{2}</td><td>字符连续出现2次,<code>a{3}</code>表示<code>aaa</code></td></tr><tr><td>{3,}</td><td>字符连续出现至少3次,<code>a{3,}</code>表示至少3个<code>a</code>连在一起</td></tr><tr><td>*</td><td>字符不限次数,不出现也行,等价于<code>{0,}</code></td></tr><tr><td>+</td><td>字符出现至少1次,等价于<code>{1,}</code></td></tr><tr><td>?</td><td>字符出现0次或者1次,等价于<code>{0,1}</code></td></tr><tr><td>│</td><td>字符两边“或”关系,<code>(a│b)c</code> 可以是<code>ac</code>或者是<code>bc</code></td></tr><tr><td>[]</td><td>字符集合,匹配中括号中某一个字符,<code>[abc]</code>可以是<code>a</code>或者<code>b</code>或者<code>c</code></td></tr><tr><td>[a-d]</td><td>字符范围,<code>[a-d]</code>表示小写字符<code>a</code>到<code>d</code>之间的某个字符</td></tr><tr><td>[^xyz]</td><td>负值字符范围,<code>[^xyz]</code>表示不能有<code>x</code>和<code>y</code>和<code>z</code></td></tr><tr><td>\w</td><td>任意单词和下划线,等价于<code>[A-Za-z0-9_]</code></td></tr><tr><td>\d</td><td>任意数字,等价于<code>[0-9]</code></td></tr></tbody></table><p>注意:</p><ul><li>不同语言的语法不一样,注意灵活使用转义字符进行报错转义</li><li>小括号<code>()</code>依然代表优先级,但是中括号有额外含义</li></ul><h3 id="二、简单事例"><a href="#二、简单事例" class="headerlink" title="二、简单事例"></a>二、简单事例</h3><h4 id="1、匹配字符串abc"><a href="#1、匹配字符串abc" class="headerlink" title="1、匹配字符串abc"></a>1、匹配字符串<code>abc</code></h4><figure class="highlight objectivec"><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><code class="hljs objectivec"><span class="hljs-built_in">NSString</span> *reg = <span class="hljs-string">@"^abc$"</span>;<br><span class="hljs-built_in">NSPredicate</span> *predicate = [<span class="hljs-built_in">NSPredicate</span> predicateWithFormat:<span class="hljs-string">@"SELF MATCHES %@"</span>, reg];<br><span class="hljs-built_in">BOOL</span> validate1 = [predicate evaluateWithObject:<span class="hljs-string">@"abc"</span>];<span class="hljs-comment">//YES</span><br></code></pre></td></tr></table></figure><p>注意:</p><ul><li><code>^</code>和<code>$</code>代表的开头和结尾,事实上定死了字符串<code>abc</code></li></ul><h4 id="2、匹配字符串a-b-1"><a href="#2、匹配字符串a-b-1" class="headerlink" title="2、匹配字符串a*b.1"></a>2、匹配字符串<code>a*b.1</code></h4><figure class="highlight objectivec"><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><code class="hljs objectivec"><span class="hljs-comment">//iOS代码</span><br><span class="hljs-built_in">NSString</span> *reg = <span class="hljs-string">@"^a[*]b[.]1$"</span>;<br><span class="hljs-built_in">NSPredicate</span> *predicate = [<span class="hljs-built_in">NSPredicate</span> predicateWithFormat:<span class="hljs-string">@"SELF MATCHES %@"</span>, reg];<br><span class="hljs-built_in">BOOL</span> validate1 = [predicate evaluateWithObject:<span class="hljs-string">@"a*b.1"</span>];<span class="hljs-comment">//YES</span><br></code></pre></td></tr></table></figure><figure class="highlight awk"><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><code class="hljs awk"><span class="hljs-regexp">//</span>javaScript代码<br><span class="hljs-regexp">/^a[*]b[.]1$/</span>.test(<span class="hljs-string">'a*b.1'</span>);<span class="hljs-regexp">//</span>true<br><span class="hljs-regexp">/^a\*b\.1$/</span>.test(<span class="hljs-string">'a*b.1'</span>);<span class="hljs-regexp">//</span>true<br></code></pre></td></tr></table></figure><p>注意:</p><ul><li><code>iOS</code>代码中只能使用<code>[]</code>获取特殊字符,<code>javaScript</code>代码中可以使用<code>[]</code>或者转义字符</li></ul><h4 id="3、匹配以-m结尾的字符串"><a href="#3、匹配以-m结尾的字符串" class="headerlink" title="3、匹配以.m结尾的字符串"></a>3、匹配以<code>.m</code>结尾的字符串</h4><figure class="highlight objectivec"><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><code class="hljs objectivec"><span class="hljs-comment">//iOS代码</span><br><span class="hljs-built_in">NSString</span> *reg = <span class="hljs-string">@"^\\w+[.]m$"</span>;<br><span class="hljs-built_in">NSPredicate</span> *predicate = [<span class="hljs-built_in">NSPredicate</span> predicateWithFormat:<span class="hljs-string">@"SELF MATCHES %@"</span>, reg];<br><span class="hljs-built_in">BOOL</span> validate1 = [predicate evaluateWithObject:<span class="hljs-string">@"a.m"</span>];<span class="hljs-comment">//YES</span><br><br><span class="hljs-comment">//iOS代码</span><br><span class="hljs-built_in">NSString</span> *reg = <span class="hljs-string">@"[A-Za-z0-9_]+[.]m$"</span>;<br><span class="hljs-built_in">NSPredicate</span> *predicate = [<span class="hljs-built_in">NSPredicate</span> predicateWithFormat:<span class="hljs-string">@"SELF MATCHES %@"</span>, reg];<br><span class="hljs-built_in">BOOL</span> validate1 = [predicate evaluateWithObject:<span class="hljs-string">@"a.m"</span>];<span class="hljs-comment">//YES</span><br></code></pre></td></tr></table></figure><figure class="highlight awk"><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><code class="hljs awk"><span class="hljs-regexp">//</span>javaScript代码<br><span class="hljs-regexp">/\w+[.]m$/</span>.test(<span class="hljs-string">'a.m'</span>);<span class="hljs-regexp">//</span>true<br><span class="hljs-regexp">/[A-Za-z0-9_]+[.]js$/</span>.test(<span class="hljs-string">'m.js'</span>);<span class="hljs-regexp">//</span>true<br></code></pre></td></tr></table></figure><p>注意:</p><ul><li><code>iOS</code>代码中<code>\w</code>元字符需要转义,<code>javaScript</code>代码中不需要</li><li><code>\w</code>字符可以使用相同意义的<code>[A-Za-z0-9_]</code>替代</li><li><code>+</code>字符代表至少1次</li></ul><h4 id="4、匹配一个非0开头的非负整数,但可以是0本身"><a href="#4、匹配一个非0开头的非负整数,但可以是0本身" class="headerlink" title="4、匹配一个非0开头的非负整数,但可以是0本身"></a>4、匹配一个非0开头的非负整数,但可以是0本身</h4><figure class="highlight objectivec"><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><code class="hljs objectivec"><span class="hljs-comment">//iOS代码</span><br><span class="hljs-built_in">NSString</span> *reg = <span class="hljs-string">@"^(0|[1-9][0-9]*)$"</span>;<br><span class="hljs-built_in">NSPredicate</span> *predicate = [<span class="hljs-built_in">NSPredicate</span> predicateWithFormat:<span class="hljs-string">@"SELF MATCHES %@"</span>, reg];<br><span class="hljs-built_in">BOOL</span> validate1 = [predicate evaluateWithObject:<span class="hljs-string">@"123"</span>];<span class="hljs-comment">//YES</span><br></code></pre></td></tr></table></figure><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs awk"><span class="hljs-regexp">//</span>javaScript代码<br><span class="hljs-regexp">/^(0|[1-9][0-9]*)$/</span>.test(<span class="hljs-string">'123'</span>);<span class="hljs-regexp">//</span>true<br></code></pre></td></tr></table></figure><p>注意:</p><ul><li><code>|</code>字符代表或的运算,<code>*</code>代表不限次数</li><li>通过<code>()</code>将<code>|</code>包裹,达到或运算的效果</li></ul><h3 id="三、简单应用"><a href="#三、简单应用" class="headerlink" title="三、简单应用"></a>三、简单应用</h3><h4 id="1、验证密码复杂度"><a href="#1、验证密码复杂度" class="headerlink" title="1、验证密码复杂度"></a>1、验证密码复杂度</h4><ul><li>6到8位</li><li>必须同时包括大写、小写、数字三种类型,不能含有其他类型字符</li><li>不能以数字开头</li></ul><blockquote><p>首先分析必须包含三种类型,共6种情况,排除不能以数字开头,剩余4种情况,所以可以遍历所有的情况,如下代码,先单独判断长度,通过后遍历四种情况</p></blockquote><figure class="highlight inform7"><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><code class="hljs inform7">//iOS代码<br>NSString *str = @<span class="hljs-string">"AzA0z"</span>;<br>NSString *reg1 = @<span class="hljs-string">"^<span class="hljs-subst">[A-Za-z0-9]</span>{6,8}$"</span>;<br>NSPredicate *predicate1 = <span class="hljs-comment">[NSPredicate predicateWithFormat:@"SELF MATCHES %@", reg1]</span>;<br>if (<span class="hljs-comment">[predicate1 evaluateWithObject:str]</span>) {<br> NSString *reg2 = @<span class="hljs-string">"^((<span class="hljs-subst">[a-z]</span><span class="hljs-subst">[a-zA-Z0-9]</span>*<span class="hljs-subst">[A-Z]</span>+<span class="hljs-subst">[a-zA-Z0-9]</span>*<span class="hljs-subst">[0-9]</span>+)|(<span class="hljs-subst">[a-z]</span><span class="hljs-subst">[a-zA-Z0-9]</span>*<span class="hljs-subst">[0-9]</span>+<span class="hljs-subst">[a-zA-Z0-9]</span>*<span class="hljs-subst">[A-Z]</span>+)|(<span class="hljs-subst">[A-Z]</span><span class="hljs-subst">[a-zA-Z0-9]</span>*<span class="hljs-subst">[a-z]</span>+<span class="hljs-subst">[a-zA-Z0-9]</span>*<span class="hljs-subst">[0-9]</span>+)|(<span class="hljs-subst">[A-Z]</span><span class="hljs-subst">[a-zA-Z0-9]</span>*<span class="hljs-subst">[0-9]</span>+<span class="hljs-subst">[a-zA-Z0-9]</span>*<span class="hljs-subst">[a-z]</span>+))<span class="hljs-subst">[0-9a-zA-Z]</span>*$"</span>;<br> NSPredicate *predicate2 = <span class="hljs-comment">[NSPredicate predicateWithFormat:@"SELF MATCHES %@", reg2]</span>;<br> BOOL validate2 = <span class="hljs-comment">[predicate2 evaluateWithObject:str]</span>;<br>}<br></code></pre></td></tr></table></figure><h3 id="四、进阶应用"><a href="#四、进阶应用" class="headerlink" title="四、进阶应用"></a>四、进阶应用</h3><p>文档顶部介绍的元字符是常用的简单字符,还有一些复杂一点的字符可以看一下</p><ul><li><code>(?:pattern)</code>:匹配 <code>pattern</code> 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 “或” 字符 <code>(|)</code> 来组合一个模式的各个部分是很有用。例如, <code>'industr(?:y|ies)</code> 就是一个比 <code>'industry|industries'</code> 更简略的表达式。</li><li><code>(?=pattern)</code>:正向肯定预查(<code>look ahead positive assert</code>),在任何匹配<code>pattern</code>的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,<code>"Windows(?=95|98|NT|2000)"</code>能匹配<code>"Windows2000"</code>中的<code>"Windows"</code>,但不能匹配<code>"Windows3.1"</code>中的<code>"Windows"</code>。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。</li><li><code>(?!pattern)</code>:正向否定预查<code>(negative assert)</code>,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如<code>"Windows(?!95|98|NT|2000)"</code>能匹配<code>"Windows3.1"中的"Windows"</code>,但不能匹配<code>"Windows2000"中的"Windows"</code>。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。</li><li><code>(?<=pattern)</code>:反向<code>(look behind)</code>肯定预查,与正向肯定预查类似,只是方向相反。例如,<code>"(?<=95|98|NT|2000)Windows"</code>能匹配<code>"2000Windows"</code>中的<code>"Windows"</code>,但不能匹配<code>"3.1Windows"</code>中的”Windows”。</li><li><code>(?<!pattern)</code>:反向否定预查,与正向否定预查类似,只是方向相反。例如<code>"(?<!95|98|NT|2000)Windows"</code>能匹配<code>"3.1Windows"</code>中的<code>"Windows"</code>,但不能匹配<code>"2000Windows"中的"Windows"</code>。</li></ul><p>以上面密码复杂度的应用来说,也可以使用如下代码</p><figure class="highlight objectivec"><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><code class="hljs objectivec"><span class="hljs-comment">//iOS代码</span><br><span class="hljs-built_in">NSString</span> *str = <span class="hljs-string">@"aA1"</span>;<br><span class="hljs-built_in">NSString</span> *reg1 = <span class="hljs-string">@"(?=[a-zA-Z0-9]*[A-Z])(?=[a-zA-Z0-9]*[a-z])(?=[a-zA-Z0-9]*[0-9])[a-zA-Z0-9]{3,}$"</span>;<br><span class="hljs-built_in">NSPredicate</span> *predicate1 = [<span class="hljs-built_in">NSPredicate</span> predicateWithFormat:<span class="hljs-string">@"SELF MATCHES %@"</span>, reg1];<br><span class="hljs-built_in">BOOL</span> validate1 = [predicate1 evaluateWithObject:str];<span class="hljs-comment">//YES</span><br></code></pre></td></tr></table></figure><p>当然除了<code>?=</code>字符外,还可以有很多种写法,此处不一一枚举了。</p><p>正则表达式,入门容易,精通难,只有持之以恒的练习才能真正的精通。</p>]]></content>
<categories>
<category>iOS</category>
</categories>
<tags>
<tag>iOS</tag>
<tag>正则</tag>
</tags>
</entry>
<entry>
<title>NSPredicate谓词简析</title>
<link href="/2019/03/22/NSPredicate%E8%B0%93%E8%AF%8D%E7%AE%80%E6%9E%90/"/>
<url>/2019/03/22/NSPredicate%E8%B0%93%E8%AF%8D%E7%AE%80%E6%9E%90/</url>
<content type="html"><![CDATA[<h3 id="一、NSPredicate定义"><a href="#一、NSPredicate定义" class="headerlink" title="一、NSPredicate定义"></a>一、NSPredicate定义</h3><p><code>NSPredicate</code>是<code>Foundation</code>框架中提供的一个类,中文翻译成谓词,官方文档中的注释如下:</p><figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs pgsql">// Predicates wrap <span class="hljs-keyword">some</span> combination <span class="hljs-keyword">of</span> expressions <span class="hljs-keyword">and</span> operators <span class="hljs-keyword">and</span> <span class="hljs-keyword">when</span> evaluated <span class="hljs-keyword">return</span> a <span class="hljs-type">BOOL</span>.<br></code></pre></td></tr></table></figure><p>意思为包含表达式和运算符的某种组合,并在计算时返回<code>BOOL</code>值,以次我们可以简单推测其主要的作用是用来比较的</p><p>官方文档释义如下:</p><blockquote><p>A definition of logical conditions used to constrain a search either for a fetch or for in-memory filtering.</p></blockquote><blockquote><p>Predicates represent logical conditions, which you can use to filter collections of objects. Although it’s common to create predicates directly from instances of NSComparisonPredicate, NSCompoundPredicate, and NSExpression, you often create predicates from a format string which is parsed by the class methods on NSPredicate.</p></blockquote><h3 id="二、相关方法和属性"><a href="#二、相关方法和属性" class="headerlink" title="二、相关方法和属性"></a>二、相关方法和属性</h3><p>经常使用的是如下的初始化方法,通过格式化字符串来进行谓词对象的初始化</p><figure class="highlight objectivec"><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><code class="hljs objectivec">+ (<span class="hljs-built_in">NSPredicate</span> *)predicateWithFormat:(<span class="hljs-built_in">NSString</span> *)predicateFormat argumentArray:(<span class="hljs-keyword">nullable</span> <span class="hljs-built_in">NSArray</span> *)arguments;<br>+ (<span class="hljs-built_in">NSPredicate</span> *)predicateWithFormat:(<span class="hljs-built_in">NSString</span> *)predicateFormat, ...;<br>+ (<span class="hljs-built_in">NSPredicate</span> *)predicateWithFormat:(<span class="hljs-built_in">NSString</span> *)predicateFormat arguments:(va_list)argList;<br></code></pre></td></tr></table></figure><p>例如:</p><figure class="highlight objectivec"><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><code class="hljs objectivec"><span class="hljs-comment">//检测length为5的对象</span><br><span class="hljs-built_in">NSPredicate</span> *predicate = [<span class="hljs-built_in">NSPredicate</span> predicateWithFormat:<span class="hljs-string">@"length = 5"</span>];<br><span class="hljs-built_in">NSArray</span> *test = @[<span class="hljs-string">@"1213"</span>, <span class="hljs-string">@"dddda"</span>, <span class="hljs-string">@"adas"</span>, <span class="hljs-string">@"f"</span>, <span class="hljs-string">@"ccccc"</span>];<br><span class="hljs-built_in">NSArray</span> *result = [test filteredArrayUsingPredicate:predicate];<br><span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"%@"</span>, result);<span class="hljs-comment">//打印result值得到数组中的两个值@"dddda"和@"ccccc"</span><br></code></pre></td></tr></table></figure><p>使用字符串初始化时,需要注意语法的正确,以及正确的转义字符,否则会引起崩溃。</p><p>除了字符串初始化<code>NSPredicate</code>对象以外,通过模板来创建谓词对象也是一种十分常用的方式,模板中只有键名,没有键值,键值需要在字典中进行提供,例如:</p><figure class="highlight nix"><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><code class="hljs nix">NSPredicate *<span class="hljs-attr">predicate</span> = [NSPredicate predicateWithFormat:@<span class="hljs-string">"length = $LENGTH"</span>];<br><span class="hljs-attr">predicate</span> = [predicate predicateWithSubstitutionVariables:@{@<span class="hljs-string">"LENGTH"</span> : @<span class="hljs-number">5</span>}];<br>NSArray *<span class="hljs-attr">test</span> = @[@<span class="hljs-string">"1213"</span>, @<span class="hljs-string">"dddda"</span>, @<span class="hljs-string">"adas"</span>, @<span class="hljs-string">"f"</span>, @<span class="hljs-string">"ccccc"</span>];<br>NSArray *<span class="hljs-attr">result</span> = [test filteredArrayUsingPredicate:predicate];<br>NSLog(@<span class="hljs-string">"%@"</span>, result);//值为@<span class="hljs-string">"dddda"</span>和@<span class="hljs-string">"ccccc"</span>数组<br></code></pre></td></tr></table></figure><p>其他属性与方法解析如下:</p><figure class="highlight objectivec"><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></pre></td><td class="code"><pre><code class="hljs objectivec"><span class="hljs-comment">//创建一个总是验证通过或不通过的谓词对象,如果是验证通过的,则任何检索都会成功进行返回,否则任何检索都会失败且不返回任何对象</span><br>+ (<span class="hljs-built_in">NSPredicate</span> *)predicateWithValue:(<span class="hljs-built_in">BOOL</span>)value;<br><br><span class="hljs-comment">//检索函数的Block版本,可以更加方遍的书写逻辑,类似遍历方法</span><br>+ (<span class="hljs-built_in">NSPredicate</span>*)predicateWithBlock:(<span class="hljs-built_in">BOOL</span> (^)(<span class="hljs-keyword">id</span> _Nullable evaluatedObject, <span class="hljs-built_in">NSDictionary</span><<span class="hljs-built_in">NSString</span> *, <span class="hljs-keyword">id</span>> * _Nullable bindings))block API_AVAILABLE(macos(<span class="hljs-number">10.6</span>), ios(<span class="hljs-number">4.0</span>), watchos(<span class="hljs-number">2.0</span>), tvos(<span class="hljs-number">9.0</span>));<br><br><span class="hljs-comment">//格式化字符串属性</span><br><span class="hljs-keyword">@property</span> (<span class="hljs-keyword">readonly</span>, <span class="hljs-keyword">copy</span>) <span class="hljs-built_in">NSString</span> *predicateFormat;<br><br><span class="hljs-comment">//检查一个Object对象是否可以通过验证</span><br>- (<span class="hljs-built_in">BOOL</span>)evaluateWithObject:(<span class="hljs-keyword">nullable</span> <span class="hljs-keyword">id</span>)object; <span class="hljs-comment">// evaluate a predicate against a single object</span><br><br><span class="hljs-comment">//用谓词模板进行对象的验证</span><br>- (<span class="hljs-built_in">BOOL</span>)evaluateWithObject:(<span class="hljs-keyword">nullable</span> <span class="hljs-keyword">id</span>)object substitutionVariables:(<span class="hljs-keyword">nullable</span> <span class="hljs-built_in">NSDictionary</span><<span class="hljs-built_in">NSString</span> *, <span class="hljs-keyword">id</span>> *)bindings API_AVAILABLE(macos(<span class="hljs-number">10.5</span>), ios(<span class="hljs-number">3.0</span>), watchos(<span class="hljs-number">2.0</span>), tvos(<span class="hljs-number">9.0</span>)); <span class="hljs-comment">// single pass evaluation substituting variables from the bindings dictionary for any variable expressions encountered</span><br><br><span class="hljs-comment">//允许安全评估</span><br>- (<span class="hljs-keyword">void</span>)allowEvaluation API_AVAILABLE(macos(<span class="hljs-number">10.9</span>), ios(<span class="hljs-number">7.0</span>), watchos(<span class="hljs-number">2.0</span>), tvos(<span class="hljs-number">9.0</span>)); <span class="hljs-comment">// Force a predicate which was securely decoded to allow evaluation</span><br></code></pre></td></tr></table></figure><p>不同的初始化方法可以搭配不同<code>filter</code>的方法,此处不再一一演示各个方法的效果。</p><figure class="highlight less"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><code class="hljs less"><span class="hljs-variable">@interface</span> NSArray<ObjectType> (NSPredicateSupport)<br><span class="hljs-comment">//根据对象数组计算谓词并返回已过滤的数组</span><br>- (NSArray<ObjectType> *)<span class="hljs-attribute">filteredArrayUsingPredicate</span>:(NSPredicate *)predicate; <span class="hljs-comment">// evaluate a predicate against an array of objects and return a filtered array</span><br><span class="hljs-variable">@end</span><br><br><span class="hljs-variable">@interface</span> NSMutableArray<ObjectType> (NSPredicateSupport)<br><span class="hljs-comment">//根据对象数组计算谓词并直接过滤可变数组</span><br>- (void)<span class="hljs-attribute">filterUsingPredicate</span>:(NSPredicate *)predicate; <span class="hljs-comment">// evaluate a predicate against an array of objects and filter the mutable array directly</span><br><span class="hljs-variable">@end</span><br><br><br><span class="hljs-variable">@interface</span> NSSet<ObjectType> (NSPredicateSupport)<br><span class="hljs-comment">//根据一组对象评估谓词并返回一个过滤集</span><br>- (NSSet<ObjectType> *)<span class="hljs-attribute">filteredSetUsingPredicate</span>:(NSPredicate *)predicate API_AVAILABLE(macos(<span class="hljs-number">10.5</span>), ios(<span class="hljs-number">3.0</span>), watchos(<span class="hljs-number">2.0</span>), tvos(<span class="hljs-number">9.0</span>)); <span class="hljs-comment">// evaluate a predicate against a set of objects and return a filtered set</span><br><span class="hljs-variable">@end</span><br><br><span class="hljs-variable">@interface</span> NSMutableSet<ObjectType> (NSPredicateSupport)<br><span class="hljs-comment">//根据一组对象评估谓词并直接过滤可变集</span><br>- (void)<span class="hljs-attribute">filterUsingPredicate</span>:(NSPredicate *)predicate API_AVAILABLE(macos(<span class="hljs-number">10.5</span>), ios(<span class="hljs-number">3.0</span>), watchos(<span class="hljs-number">2.0</span>), tvos(<span class="hljs-number">9.0</span>)); <span class="hljs-comment">// evaluate a predicate against a set of objects and filter the mutable set directly</span><br><span class="hljs-variable">@end</span><br><br><span class="hljs-variable">@interface</span> NSOrderedSet<ObjectType> (NSPredicateSupport)<br><span class="hljs-comment">//根据有序对象集评估谓词并返回已过滤的有序集</span><br>- (NSOrderedSet<ObjectType> *)<span class="hljs-attribute">filteredOrderedSetUsingPredicate</span>:(NSPredicate *)p API_AVAILABLE(macos(<span class="hljs-number">10.7</span>), ios(<span class="hljs-number">5.0</span>), watchos(<span class="hljs-number">2.0</span>), tvos(<span class="hljs-number">9.0</span>)); <span class="hljs-comment">// evaluate a predicate against an ordered set of objects and return a filtered ordered set</span><br><br><span class="hljs-variable">@end</span><br><br><span class="hljs-variable">@interface</span> NSMutableOrderedSet<ObjectType> (NSPredicateSupport)<br><span class="hljs-comment">//根据有序对象集评估谓词,并直接过滤可变有序集</span><br>- (void)<span class="hljs-attribute">filterUsingPredicate</span>:(NSPredicate *)p API_AVAILABLE(macos(<span class="hljs-number">10.7</span>), ios(<span class="hljs-number">5.0</span>), watchos(<span class="hljs-number">2.0</span>), tvos(<span class="hljs-number">9.0</span>)); <span class="hljs-comment">// evaluate a predicate against an ordered set of objects and filter the mutable ordered set directly</span><br><br><span class="hljs-variable">@end</span><br></code></pre></td></tr></table></figure><h3 id="三、拓展"><a href="#三、拓展" class="headerlink" title="三、拓展"></a>三、拓展</h3><p>前面官方文档中提到了几个<code>NSPredicate</code>的子类</p><h4 id="1、NSComparisonPredicate比较谓词"><a href="#1、NSComparisonPredicate比较谓词" class="headerlink" title="1、NSComparisonPredicate比较谓词"></a>1、NSComparisonPredicate比较谓词</h4><p>同样是获取数组中的指定元素,相同的例子可以使用NSComparisonPredicate写成如下形式:</p><figure class="highlight objectivec"><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><code class="hljs objectivec"><span class="hljs-comment">//创建左侧表达式对象 对应为键</span><br><span class="hljs-built_in">NSExpression</span> *left = [<span class="hljs-built_in">NSExpression</span> expressionForKeyPath:<span class="hljs-string">@"length"</span>];<br><span class="hljs-comment">//创建右侧表达式对象 对应为值</span><br><span class="hljs-built_in">NSExpression</span> *right = [<span class="hljs-built_in">NSExpression</span> expressionForConstantValue:@<span class="hljs-number">5</span>];<br><span class="hljs-comment">//创建比较谓词对象 这里设置为严格等于</span><br><span class="hljs-built_in">NSComparisonPredicate</span> *cPredicate = [<span class="hljs-built_in">NSComparisonPredicate</span> predicateWithLeftExpression:left rightExpression:right modifier:<span class="hljs-built_in">NSDirectPredicateModifier</span> type:<span class="hljs-built_in">NSEqualToPredicateOperatorType</span> options:<span class="hljs-built_in">NSCaseInsensitivePredicateOption</span>];<br><span class="hljs-built_in">NSArray</span> *test = @[<span class="hljs-string">@"1213"</span>, <span class="hljs-string">@"dddda"</span>, <span class="hljs-string">@"adas"</span>, <span class="hljs-string">@"f"</span>, <span class="hljs-string">@"ccccc"</span>];<br><span class="hljs-built_in">NSArray</span> *result = [test filteredArrayUsingPredicate:cPredicate];<br></code></pre></td></tr></table></figure><p>其中包含的几个枚举如下</p><figure class="highlight awk"><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><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><code class="hljs awk"><span class="hljs-regexp">//</span> Describes how the operator is modified: can be direct, ALL, or ANY<br>typedef NS_ENUM(NSUInteger, NSComparisonPredicateModifier) {<br>NSDirectPredicateModifier = <span class="hljs-number">0</span>, <span class="hljs-regexp">//</span> Do a direct comparison<span class="hljs-regexp">//</span>直接进行比较操作<br>NSAllPredicateModifier, <span class="hljs-regexp">//</span> ALL toMany.x = y<span class="hljs-regexp">//</span>只有当内部所有元素都通过验证时,才算通过<br>NSAnyPredicateModifier <span class="hljs-regexp">//</span> ANY toMany.x = y<span class="hljs-regexp">//</span>当内部有一个元素满足时,就算通过验证<br><span class="hljs-regexp">//</span>后两个一般用于数组<br>};<br><br><span class="hljs-regexp">//</span> Type basic set of operators defined. Most are obvious; NSCustomSelectorPredicateOperatorType allows a developer to create an operator which uses the custom selector specified <span class="hljs-keyword">in</span> the constructor to <span class="hljs-keyword">do</span> the evaluation.<br>typedef NS_ENUM(NSUInteger, NSPredicateOperatorType) {<br>NSLessThanPredicateOperatorType = <span class="hljs-number">0</span>, <span class="hljs-regexp">//</span> compare: returns NSOrderedAscending<span class="hljs-regexp">//</span> 小于<br>NSLessThanOrEqualToPredicateOperatorType, <span class="hljs-regexp">//</span> compare: returns NSOrderedAscending || NSOrderedSame<span class="hljs-regexp">//</span> 小于等于<br>NSGreaterThanPredicateOperatorType, <span class="hljs-regexp">//</span> compare: returns NSOrderedDescending<span class="hljs-regexp">//</span> 大于<br>NSGreaterThanOrEqualToPredicateOperatorType, <span class="hljs-regexp">//</span> compare: returns NSOrderedDescending || NSOrderedSame<span class="hljs-regexp">//</span> 大于等于<br>NSEqualToPredicateOperatorType, <span class="hljs-regexp">//</span> isEqual: returns true<span class="hljs-regexp">//</span> 等于<br>NSNotEqualToPredicateOperatorType, <span class="hljs-regexp">//</span> isEqual: returns false<span class="hljs-regexp">//</span>不等于<br>NSMatchesPredicateOperatorType,<span class="hljs-regexp">//</span> 正则比配<br>NSLikePredicateOperatorType,<span class="hljs-regexp">//</span> Like匹配<br>NSBeginsWithPredicateOperatorType,<span class="hljs-regexp">//</span> 左边的表达式以右边的表达式作为开头<br>NSEndsWithPredicateOperatorType,<span class="hljs-regexp">//</span> 左边的表达式以右边的表达式作为结尾<br>NSInPredicateOperatorType, <span class="hljs-regexp">//</span> rhs contains lhs returns true<span class="hljs-regexp">//</span> 左边的表达式出现在右边的集合中<br>NSCustomSelectorPredicateOperatorType,<span class="hljs-regexp">//</span> 使用自定义的函数来进行验证<br>NSContainsPredicateOperatorType API_AVAILABLE(macos(<span class="hljs-number">10.5</span>), ios(<span class="hljs-number">3.0</span>), watchos(<span class="hljs-number">2.0</span>), tvos(<span class="hljs-number">9.0</span>)) = <span class="hljs-number">99</span>, <span class="hljs-regexp">//</span> lhs contains rhs returns true<span class="hljs-regexp">//</span> 左边的集合包括右边的元素<br>NSBetweenPredicateOperatorType API_AVAILABLE(macos(<span class="hljs-number">10.5</span>), ios(<span class="hljs-number">3.0</span>), watchos(<span class="hljs-number">2.0</span>), tvos(<span class="hljs-number">9.0</span>))<span class="hljs-regexp">//</span> 左边表达式的值在右边的范围中<br>};<br><br><span class="hljs-regexp">//</span> Flags(s) that can be passed to the factory to indicate that a operator operating on strings should <span class="hljs-keyword">do</span> so <span class="hljs-keyword">in</span> a case insensitive fashion.<br>typedef NS_OPTIONS(NSUInteger, NSComparisonPredicateOptions) {<br>NSCaseInsensitivePredicateOption = <span class="hljs-number">0</span>x01,<span class="hljs-regexp">//</span> 不区分大小写<br>NSDiacriticInsensitivePredicateOption = <span class="hljs-number">0</span>x02,<span class="hljs-regexp">//</span> 不区分读音符号<br>NSNormalizedPredicateOption API_AVAILABLE(macos(<span class="hljs-number">10.6</span>), ios(<span class="hljs-number">4.0</span>), watchos(<span class="hljs-number">2.0</span>), tvos(<span class="hljs-number">9.0</span>)) = <span class="hljs-number">0</span>x04, <span class="hljs-regexp">/* Indicate that the strings to be compared have been preprocessed; this supersedes other options and is intended as a performance optimization option */</span><span class="hljs-regexp">//</span>比较前进行预处理 代替上面两个选项<br>};<br></code></pre></td></tr></table></figure><h4 id="2、NSCompoundPredicate复合谓词"><a href="#2、NSCompoundPredicate复合谓词" class="headerlink" title="2、NSCompoundPredicate复合谓词"></a>2、NSCompoundPredicate复合谓词</h4><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><code class="hljs swift"><span class="hljs-comment">// 创建与运算</span><br><span class="hljs-operator">+</span> (<span class="hljs-type">NSCompoundPredicate</span> <span class="hljs-operator">*</span>)andPredicateWithSubpredicates:(<span class="hljs-type">NSArray</span><<span class="hljs-type">NSPredicate</span> *> <span class="hljs-operator">*</span>)subpredicates <span class="hljs-type">NS_SWIFT_NAME</span>(<span class="hljs-keyword">init</span>(andPredicateWithSubpredicates:));<br><span class="hljs-comment">// 创建或运算</span><br><span class="hljs-operator">+</span> (<span class="hljs-type">NSCompoundPredicate</span> <span class="hljs-operator">*</span>)orPredicateWithSubpredicates:(<span class="hljs-type">NSArray</span><<span class="hljs-type">NSPredicate</span> *> <span class="hljs-operator">*</span>)subpredicates <span class="hljs-type">NS_SWIFT_NAME</span>(<span class="hljs-keyword">init</span>(orPredicateWithSubpredicates:));<br><span class="hljs-comment">// 创建非运算</span><br><span class="hljs-operator">+</span> (<span class="hljs-type">NSCompoundPredicate</span> <span class="hljs-operator">*</span>)notPredicateWithSubpredicate:(<span class="hljs-type">NSPredicate</span> <span class="hljs-operator">*</span>)predicate <span class="hljs-type">NS_SWIFT_NAME</span>(<span class="hljs-keyword">init</span>(notPredicateWithSubpredicate:));<br></code></pre></td></tr></table></figure><h3 id="四、iOS正则使用"><a href="#四、iOS正则使用" class="headerlink" title="四、iOS正则使用"></a>四、iOS正则使用</h3><p><code>NSPredicate</code>谓词的用法比较冷门,但是其中包含了一个非常重要的正则表达式的用法,通过<code>SELF MATCHES</code>的格式化字符串,引入通用的正则表达式的判断逻辑,例如:</p><figure class="highlight objectivec"><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><code class="hljs objectivec"><span class="hljs-comment">// 判断字符串是否符合规则</span><br><span class="hljs-built_in">NSString</span> *reg = <span class="hljs-string">@"^[0-9]+$"</span>;<br><span class="hljs-built_in">NSPredicate</span> *predicate = [<span class="hljs-built_in">NSPredicate</span> predicateWithFormat:<span class="hljs-string">@"SELF MATCHES %@"</span>, reg];<br><span class="hljs-built_in">BOOL</span> validate1 = [predicate evaluateWithObject:<span class="hljs-string">@"qw"</span>];<span class="hljs-comment">//NO</span><br><span class="hljs-built_in">BOOL</span> validate2 = [predicate evaluateWithObject:<span class="hljs-string">@"12"</span>];<span class="hljs-comment">//YES</span><br></code></pre></td></tr></table></figure><p>需要注意的点如下:</p><ul><li><code>iOS</code>中正则表达式有些字符需要有额外的转义,否则会崩溃</li><li><code>NSPredicate</code>中只提供了匹配方法,没有其他语音的提取方法,一些提取的操作需要使用<code>iOS</code>其他方法配合使用</li></ul><p>虽然谓词比较冷门,但是关于谓词的使用,还是有很多灵活的用法等待我们去研究。</p>]]></content>