forked from qiubaiying/qiubaiying.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfeed.xml
More file actions
1012 lines (661 loc) · 71.1 KB
/
feed.xml
File metadata and controls
1012 lines (661 loc) · 71.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>BY Blog</title>
<description>每个胜利背后都有许多尝试</description>
<link>http://localhost:4000/</link>
<atom:link href="http://localhost:4000/feed.xml" rel="self" type="application/rss+xml" />
<pubDate>Fri, 10 Feb 2017 16:27:45 +0800</pubDate>
<lastBuildDate>Fri, 10 Feb 2017 16:27:45 +0800</lastBuildDate>
<generator>Jekyll v3.3.1</generator>
<item>
<title>Mac 快速调出终端</title>
<description><blockquote>
<p>在Mac下快速调出终端的方法是:为终端添加一个快捷键打开方式</p>
</blockquote>
<h2 id="为终端添加一个快捷键打开方式">为终端添加一个快捷键打开方式</h2>
<p>打开Mac下自带的软件 <strong>Automator</strong></p>
<p><img src="https://ww2.sinaimg.cn/large/006tKfTcgy1fckb184f74j319v0q01kx.jpg" alt="" /></p>
<p>新建文稿</p>
<p><img src="https://ww1.sinaimg.cn/large/006tKfTcgy1fckb6zzo28j30mo0fvgn7.jpg" alt="" /></p>
<p>创建一个服务</p>
<p><img src="https://ww1.sinaimg.cn/large/006tKfTcgy1fckb93qmy5j30g00fh0vq.jpg" alt="" /></p>
<p><img src="https://ww2.sinaimg.cn/large/006tKfTcgy1fckbfe8o0zj30t10lb0wv.jpg" alt="" /></p>
<p><img src="https://ww1.sinaimg.cn/large/006tKfTcgy1fckbff4e7pj30t10lbwis.jpg" alt="" /></p>
<p>修改框内的脚本</p>
<div class="highlighter-rouge"><pre class="highlight"><code>on run {input, parameters}
tell application "Terminal"
reopen
activate
end tell
end run
</code></pre>
</div>
<p>运行:<code class="highlighter-rouge">command + R</code>,如果没有问题,则会打开终端</p>
<p><img src="https://ww2.sinaimg.cn/large/006tKfTcgy1fckaqdd2m1j30t10lb42a.jpg" alt="" /></p>
<p><img src="https://ww3.sinaimg.cn/large/006tKfTcgy1fckaq4nn9hj30iy0daaan.jpg" alt="" /></p>
<p>保存:<code class="highlighter-rouge">Command + S</code>,将其命名为<code class="highlighter-rouge">打开终端</code>或你想要的名字</p>
<p>设置快捷键</p>
<p>在 <strong>系统偏好设置</strong> -&gt; <strong>键盘设置</strong> -&gt; <strong>快捷键</strong> -&gt; <strong>服务</strong></p>
<p>选择我们创建好的 ‘<strong>打开终端</strong>‘,设置你想要的快捷键,比我我设置了<code class="highlighter-rouge">⌘+空格</code></p>
<p><img src="https://ww4.sinaimg.cn/large/006tKfTcgy1fckbvaixhnj30kw0ihq67.jpg" alt="" /></p>
<p>到此,设置完成。</p>
<p>聪明的你也许会发现,这个技巧能为所有的程序设置快捷启动。</p>
<p>将脚本中的 <code class="highlighter-rouge">Terminal</code> 替换成 其他程序就可以</p>
<div class="highlighter-rouge"><pre class="highlight"><code>on run {input, parameters}
tell application "Terminal"
reopen
activate
end tell
end run
</code></pre>
</div>
<h2 id="黑技能">黑技能</h2>
<p>既然学了 <code class="highlighter-rouge">Automator</code> ,那就在附上一个黑技能吧。为你的代码排序。在 <strong>Xcode8</strong>以前,有个插件能为代码快速排序,不过时过境迁~ 对于没用的插件而且又有患有强迫症的的小伙伴,只能手动排序了(😂).</p>
<p>首先还是创建一个服务</p>
<p>创建一个<code class="highlighter-rouge">Shell</code>脚本,</p>
<p>勾选:<code class="highlighter-rouge">用输出内容替换所选文本</code></p>
<p>输入:<code class="highlighter-rouge">sort|uniq</code></p>
<p>保存: 存为<code class="highlighter-rouge">Sort &amp; Uniq</code></p>
<p><img src="https://ww4.sinaimg.cn/large/006tKfTcgy1fckd40rgwmj30rt0ildiy.jpg" alt="" /></p>
<p><strong>选中你的代代码</strong> -&gt; <strong>鼠标右键</strong> -&gt; <strong>Servies</strong> -&gt; <strong>Sort&amp;Uniq</strong></p>
<p><img src="https://ww2.sinaimg.cn/large/006tKfTcgy1fckd6tx1dzj30h90b7mzm.jpg" alt="" /></p>
<p>排序后的代码:</p>
<p><img src="https://ww3.sinaimg.cn/large/006tKfTcgy1fckd6lak55j309j05y3yo.jpg" alt="" /></p>
</description>
<pubDate>Mon, 06 Feb 2017 00:00:00 +0800</pubDate>
<link>http://localhost:4000/2017/02/06/Mac%E5%BF%AB%E9%80%9F%E8%B0%83%E5%87%BA%E7%BB%88%E7%AB%AF/</link>
<guid isPermaLink="true">http://localhost:4000/2017/02/06/Mac%E5%BF%AB%E9%80%9F%E8%B0%83%E5%87%BA%E7%BB%88%E7%AB%AF/</guid>
<category>mac</category>
<category>效率</category>
</item>
<item>
<title>快速搭建个人博客</title>
<description><blockquote>
<p>正所谓前人栽树,后人乘凉。</p>
<p>感谢<a href="https://github.com/huxpro">Huxpro</a>提供的博客模板</p>
<p><a href="http://qiubaiying.top">我的的博客</a></p>
</blockquote>
<h1 id="前言">前言</h1>
<p>从 Jekyll 到 GitHub Pages 中间踩了许多坑,终于把我的个人博客<a href="http://qiubaiying.top">BY Blog</a>搭建出来了。。。</p>
<p>废话不多说了,开始进入正文。</p>
<h1 id="快速开始">快速开始</h1>
<h3 id="从注册一个github账号开始">从注册一个Github账号开始</h3>
<p>我采用的搭建博客的方式是使用 <a href="https://pages.github.com/">GitHub Pages</a> + <a href="http://jekyll.com.cn/">jekyll</a> 的方式。</p>
<p>要使用 GitHub Pages,首先你要注册一个<a href="https://github.com/">Github</a>账号</p>
<p><img src="https://ww4.sinaimg.cn/large/006tKfTcgy1fch0a9kz7aj31kw0z7npd.jpg" alt="" /></p>
<h3 id="拉取我的博客模板">拉取我的博客模板</h3>
<p>注册完成后搜索 <code class="highlighter-rouge">qiubaiying.github.io</code> 进入<a href="https://github.com/qiubaiying/qiubaiying.github.io">我的仓库</a></p>
<p><img src="https://ww3.sinaimg.cn/large/006tNbRwgy1fcgqjugzkpj30yy0p1mzc.jpg" alt="" /></p>
<p>点击右上角的 <strong>Fork</strong> 将我的仓库拉倒你的账号下</p>
<p>稍等一下,点击刷新,你会看到<strong>Fork</strong>了成功的页面</p>
<p><img src="https://ww3.sinaimg.cn/large/006tKfTcgy1fch1i297pjj31kw0z7thk.jpg" alt="" /></p>
<h3 id="修改仓库名">修改仓库名</h3>
<p>点击<strong>settings</strong>进入设置</p>
<p><img src="https://ww3.sinaimg.cn/large/006tNbRwgy1fcgqms2auij30yy0p1tau.jpg" alt="" /></p>
<p id="Rename"></p>
<p>修改仓库名为 <code class="highlighter-rouge">你的Github账号名.github.io</code>,然后 Rename</p>
<p><img src="https://ww4.sinaimg.cn/large/006tNbRwgy1fcgqfwtk1rj30yy0p1wg6.jpg" alt="" /></p>
<p>这时你在在浏览器中输入 <code class="highlighter-rouge">你的Github账号名.github.io</code> 例如:<code class="highlighter-rouge">baiyingqiu.github.io</code></p>
<p>你将会看到如下界面</p>
<p><img src="https://ww2.sinaimg.cn/large/006tNbRwgy1fcgquoqasqj30we0n8q4n.jpg" alt="" /></p>
<p>说明已经成功一半了😀。。。当然,还需要修改博客的配置才能变成你的博客。</p>
<p>若是出现</p>
<p><img src="https://ww3.sinaimg.cn/large/006tNbRwgy1fcgqz6dyxmj30we0n83yy.jpg" alt="" /></p>
<p>则需要 <a href="#Rename">检查一下你的仓库名是否正确</a></p>
<h3 id="整个网站结构">整个网站结构</h3>
<p>修改Blog前我们来看看Jekyll 网站的基础结构,当然我们的网站比这个复杂。</p>
<div class="highlighter-rouge"><pre class="highlight"><code>├── _config.yml
├── _drafts
| ├── begin-with-the-crazy-ideas.textile
| └── on-simplicity-in-technology.markdown
├── _includes
| ├── footer.html
| └── header.html
├── _layouts
| ├── default.html
| └── post.html
├── _posts
| ├── 2007-10-29-why-every-programmer-should-play-nethack.textile
| └── 2009-04-26-barcamp-boston-4-roundup.textile
├── _data
| └── members.yml
├── _site
├── img
└── index.html
</code></pre>
</div>
<p>很复杂看不懂是不是,不要紧,你只要记住其中几个OK了</p>
<ul>
<li><code class="highlighter-rouge">_config.yml</code> 全局配置文件</li>
<li><code class="highlighter-rouge">_posts</code> 放置博客文章的文件夹</li>
<li><code class="highlighter-rouge">img</code> 存放图片的文件夹</li>
</ul>
<p>其他的想继续深究可以<a href="http://jekyll.com.cn/docs/structure/">看这里</a></p>
<h3 id="修改博客配置">修改博客配置</h3>
<p>来到你的仓库,找到<code class="highlighter-rouge">_config.yml</code>文件,这是网站的全局配置文件。</p>
<p><img src="https://ww1.sinaimg.cn/large/006tNbRwgy1fcgrcxz8nqj30v90ulwh7.jpg" alt="" /></p>
<p>点击修改</p>
<p><img src="https://ww3.sinaimg.cn/large/006tNbRwgy1fcgrjzc232j30uz0nijt6.jpg" alt="" /></p>
<p>然后编辑<code class="highlighter-rouge">_config.yml</code>的内容</p>
<p><img src="https://ww2.sinaimg.cn/large/006tNbRwgy1fcgrnp4ihqj30uy0okwg9.jpg" alt="" /></p>
<p>接下来我们来详细说说以下配置文件的内容:</p>
<h4 id="基础设置">基础设置</h4>
<div class="highlighter-rouge"><pre class="highlight"><code># Site settings
title: You Blog #你博客的标题
SEOTitle: 你的博客 | You Blog #显示在浏览器上搜索的时候显示的标题
header-img: img/post-bg-rwd.jpg #显示在首页的背景图片
email: You@gmail.com
description: "You Blog" #网站介绍
keyword: "BY, BY Blog, 柏荧的博客, qiubaiying, 邱柏荧, iOS, Apple, iPhone" #关键词
url: "https://qiubaiying.github.io" # 这个就是填写你的博客地址
baseurl: "" # 这个我们不用填写
</code></pre>
</div>
<h4 id="侧边栏">侧边栏</h4>
<div class="highlighter-rouge"><pre class="highlight"><code># Sidebar settings
sidebar: true # 是否开启侧边栏.
sidebar-about-description: "说点装逼的话。。。"
sidebar-avatar: img/avatar-by.JPG # 你的个人头像 这里你可以改成我在img文件夹中的两张备用照片 img/avatar-m 或 avatar-g
</code></pre>
</div>
<h4 id="社交账号">社交账号</h4>
<p>若想链接其他社交平台</p>
<p><img src="https://ww3.sinaimg.cn/large/006tNbRwgy1fcgsm4plpdj307i03nt8i.jpg" alt="" /></p>
<p>在下面你的社交账号的用户名就可以了,若没有可不用填</p>
<div class="highlighter-rouge"><pre class="highlight"><code># SNS settings
RSS: false
weibo_username: qiubaiying
zhihu_username: qiubaiying
github_username: qiubaiying
facebook_username: baiying.qiu.7
</code></pre>
</div>
<h4 id="评论">评论</h4>
<p>集成了多说社会化评论,到多说注册账号,然后将<code class="highlighter-rouge">duoshuo_username</code>换成你的账号即可。</p>
<div class="highlighter-rouge"><pre class="highlight"><code># Duoshuo settings
duoshuo_username: YouName # 换成你的多说账号
# Share component is depend on Comment so we can NOT use share only.
duoshuo_share: true # set to false if you want to use Comment without Sharing
</code></pre>
</div>
<h4 id="网站统计">网站统计</h4>
<p>集成了 <a href="http://tongji.baidu.com/web/welcome/login">Baidu Analytics</a> 和 <a href="http://www.google.cn/analytics/">Google Analytics</a>,到各个网站注册拿到track_id替换下面的就可以了</p>
<p>这是我的 Google Analytics</p>
<p><img src="https://ww1.sinaimg.cn/large/006tNc79gy1fcgtqc5wf0j310i0nbt9j.jpg" alt="" /></p>
<p><strong>不要使用我的track_id</strong>😂。。。</p>
<p>若不想启用统计,直接删除或注释掉就可以了</p>
<div class="highlighter-rouge"><pre class="highlight"><code># Analytics settings
# Baidu Analytics
ba_track_id: 83e259f69b37d02a4633a2b7d960139c
# Google Analytics
ga_track_id: 'UA-90855596-1' # Format: UA-xxxxxx-xx
ga_domain: auto
</code></pre>
</div>
<h4 id="好友">好友</h4>
<div class="highlighter-rouge"><pre class="highlight"><code>friends: [
{
title: "简书·BY",
href: "http://www.jianshu.com/u/e71990ada2fd"
},{
title: "Apple",
href: "https://apple.com"
},{
title: "Apple Developer",
href: "https://developer.apple.com/"
}
]
</code></pre>
</div>
<h4 id="保存">保存</h4>
<p>讲网页拉倒底部,点击 <code class="highlighter-rouge">Commit changes</code> 提交保存</p>
<p><img src="https://ww2.sinaimg.cn/large/006tKfTcgy1fch1mpktilj31kw0z7n34.jpg" alt="" /></p>
<p>再次进入你的主页,</p>
<p><img src="https://ww2.sinaimg.cn/large/006tNc79gy1fcgtqheu38j30uy0kc3zs.jpg" alt="" /></p>
<p>恭喜你,你的个人博客搭建完成了😀。</p>
<h1 id="写文章">写文章</h1>
<p>利用 Github网站 ,我们可以不用学习<a href="https://git-scm.com/">git</a>,就可以轻松管理自己的博客</p>
<p>对于轻车熟路的程序猿来说,使用git管理会更加方便。。。</p>
<h2 id="创建">创建</h2>
<p>文章统一放在网站根目录下的 <code class="highlighter-rouge">_posts</code> 的文件夹中。</p>
<p><img src="https://ww3.sinaimg.cn/large/006tNc79gy1fchoc1tz03j30vi0k978h.jpg" alt="" /></p>
<p>创建一个文件</p>
<p><img src="https://ww2.sinaimg.cn/large/006tNc79gy1fchoduzebyj30vn0eg0v7.jpg" alt="" /></p>
<p>在下面写文章,和标题,还能实时预览,最后提交保存就能看到自己的新文章了。</p>
<p><img src="https://ww2.sinaimg.cn/large/006y8lVagy1fcgweml8hjj30vd0m775r.jpg" alt="" /></p>
<h2 id="格式">格式</h2>
<p>每一篇文章文件命名采用的是<code class="highlighter-rouge">2017-02-04-Hello-2017.md</code>时间+标题的形式,空格用<code class="highlighter-rouge">-</code>替换连接。</p>
<p>文件的格式是 <code class="highlighter-rouge">.md</code> 的 <a href="http://sspai.com/25137/"><strong>MarkDown</strong></a> 文件。</p>
<p>我们的博客文章格式采用是 <strong>MarkDown</strong>+ <strong>YAML</strong> 的方式。</p>
<p><a href="http://www.ruanyifeng.com/blog/2016/07/yaml.html?f=tt"><strong>YAML</strong></a> 就是我们配置 <code class="highlighter-rouge">_config</code>文件用的语言。</p>
<p><a href="http://sspai.com/25137/"><strong>MarkDown</strong></a> 是一种轻量级的「标记语言」,很简单。<a href="http://sspai.com/25137">花半个小时看一下</a>就能熟练使用了</p>
<p>大概就是这么一个结构。</p>
<div class="highlighter-rouge"><pre class="highlight"><code>---
layout: post # 使用的布局(不需要改)
title: My First Post # 标题
subtitle: Hello World, Hello Blog #副标题
date: 2017-02-06 # 时间
author: BY # 作者
header-img: img/post-bg-2015.jpg #这篇文章标题背景图片
catalog: true # 是否归档
tags: #标签
- 生活
---
## Hey
&gt;这是我的第一篇博客。
进入你的博客主页,新的文章将会出现在你的主页上.
</code></pre>
</div>
<p>按格式创建文章后,提交保存。进入你的博客主页,新的文章将会出现在你的主页上.</p>
<p><img src="https://ww4.sinaimg.cn/large/006tKfTcgy1fch26elve4j31kw13qhdt.jpg" alt="" /></p>
<p>到这里,恭喜你!</p>
<p>你已经成功搭建了自己的个人博客以及学会在博客上撰写文字的技能了(是不是有点小兴奋🙈)。</p>
<h1 id="自定义域名">自定义域名</h1>
<p>搭建好博客之后 你可能不想直接使用 <a href="http://baiyingqiu.github.io">baiyingqiu.github.io</a> 这么长的博客域名吧, 想换成想 <a href="http://qiubaiying.top">qiubaiying.top</a> 这样简短的域名。那我们开始吧!</p>
<h2 id="购买域名">购买域名</h2>
<p>首先,你必须购买一个自己的域名。</p>
<p>我是在<a href="https://wanwang.aliyun.com/domain/?spm=5176.8006371.1007.dnetcndomain.q1ys4x">阿里云</a>购买的域名</p>
<p><img src="https://ww4.sinaimg.cn/large/006tKfTcgy1fci89zv06yj31kw11p1kx.jpg" alt="" /></p>
<p>用<strong>阿里云</strong> app也可以注册域名,域名的价格根据后缀的不同和域名的长度而分,比如我这个 <code class="highlighter-rouge">qiubaiying.top</code> 的域名第一年才只要4元~</p>
<p>域名尽量选择短一点比较好记住,注意,不能选择中文域名,比如 <code class="highlighter-rouge">张三.top</code> ,GitHub Pages <strong>无法处理中文域名</strong>,会导致你的域名在你的主页上使用。</p>
<p>注册的步骤就不在介绍了</p>
<h2 id="解析域名">解析域名</h2>
<p>注册好域名后,需要将域名解析到你的博客上</p>
<p>管理控制台 → 域名与网站(万网) → 域名</p>
<p><img src="https://ww1.sinaimg.cn/large/006tKfTcgy1fci8phk5z9j30nk0q0goy.jpg" alt="" /></p>
<p>选择你注册好的域名,点击解析</p>
<p><img src="https://ww4.sinaimg.cn/large/006tKfTcgy1fci8sg27bfj31kw0s0qdt.jpg" alt="" /></p>
<p>添加解析</p>
<p>分别添加两个<code class="highlighter-rouge">A</code> 记录类型,</p>
<p>一个主机记录为 <code class="highlighter-rouge">www</code>,代表可以解析 <code class="highlighter-rouge">www.qiubaiying.top</code>的域名</p>
<p>另一个为 <code class="highlighter-rouge">@</code>, 代表 <code class="highlighter-rouge">qiubaiying.top</code></p>
<p>记录值就是我们博客的IP地址,是 GitHub Pagas 在美国的服务器的地址 <code class="highlighter-rouge">151.101.100.133</code></p>
<p><img src="https://ww3.sinaimg.cn/large/006tKfTcgy1fci8x9412oj31kw0o4n5o.jpg" alt="" /></p>
<p>可以通过 <a href="http://ip.chinaz.com/">这个网站</a> 或者直接在终端输入<code class="highlighter-rouge">ping 你的地址</code>,查看博客的IP</p>
<div class="highlighter-rouge"><pre class="highlight"><code>ping qiubaiying.github.io
</code></pre>
</div>
<p>细心地你会发现所有人的博客都解析到 <code class="highlighter-rouge">151.101.100.133</code> 这个IP。</p>
<p>然后 GitHub Pages 再通过 CNAME记录 跳转到你的主页上。</p>
<h2 id="修改cname">修改CNAME</h2>
<p>最后一步,只需要修改 我们github仓库下的 <strong>CNAME</strong> 文件。</p>
<p>选择 <strong>CNAME</strong> 文件</p>
<p><img src="https://ww2.sinaimg.cn/large/006tKfTcgy1fci9q9ne6qj31kw0uuajm.jpg" alt="" /></p>
<p>使用的注册的域名进行替换,然后提交保存</p>
<p><img src="https://ww2.sinaimg.cn/large/006tKfTcgy1fci9rzk0naj316s0n841s.jpg" alt="" /></p>
<p>这时,输入你自己的域名,就可以解析到你的主页了。</p>
<p>大功告成!</p>
<h1 id="进阶">进阶</h1>
<p>若你对博客模板进行修改,你就要看看 Jekyll 的<a href="http://jekyll.com.cn">开发文档</a>,是中文文档哦,对英语不好的朋友简直是福利啊(比如说我😀)。</p>
<p>还要学习 <strong>Git</strong> 和 <strong>GitHub</strong> 的工作机制了及使用。</p>
<p>你可以先看看这个<a href="http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/">git教程</a>,对git有个初步的了解后,那么相信你就能将自己图片传到GitHub仓库上,或者可以说掌握了 <strong>使用git管理自己的GitHub仓库</strong> 的技能呢。</p>
<p>相信很很多人看蒙了呢,这部分教程后面再补上。那就先这样吧。</p>
<p>对于轻车熟路的程序猿来说,呵~</p>
</description>
<pubDate>Mon, 06 Feb 2017 00:00:00 +0800</pubDate>
<link>http://localhost:4000/2017/02/06/%E5%BF%AB%E9%80%9F%E6%90%AD%E5%BB%BA%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2/</link>
<guid isPermaLink="true">http://localhost:4000/2017/02/06/%E5%BF%AB%E9%80%9F%E6%90%AD%E5%BB%BA%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2/</guid>
<category>Blog</category>
</item>
<item>
<title>Hello 2017</title>
<description><blockquote>
<p>“🙉🙉🙉 ”</p>
</blockquote>
<h2 id="前言">前言</h2>
<p>BY 的 Blog 就这么开通了。</p>
<p>本来打算在年前完成 Blog 的搭建,不曾料想踩了很多坑。。。</p>
<p><a href="#build">跳过废话,直接看技术实现 </a></p>
<p>2017 年,BY Blog 总算是搭建好了。</p>
<p>最开始写博客是在<a href="www.jianshu.com">简书</a>这个平台上,简书确实不错,支持markdown在线编辑。</p>
<p>在一次偶然间,听到我的好基友 <strong>阳阳</strong> 想搭建个人主页,觉得作为一个程序员,是应该倒腾倒腾自己的Blog,于是乎就开始了撸起袖子干了。</p>
<p id="build"></p>
<hr />
<h2 id="正文">正文</h2>
<p>接下来说说搭建这个博客的技术细节。</p>
<p>正好之前就有关注过 <a href="https://pages.github.com/">GitHub Pages</a> + <a href="http://jekyllrb.com/">Jekyll</a> 快速 Building Blog 的技术方案,非常轻松时尚。</p>
<p>其优点非常明显:</p>
<ul>
<li><strong>Markdown</strong> 带来的优雅写作体验</li>
<li>非常熟悉的 Git workflow ,<strong>Git Commit 即 Blog Post</strong></li>
<li>利用 GitHub Pages 的域名和免费无限空间,不用自己折腾主机
<ul>
<li>如果需要自定义域名,也只需要简单改改 DNS 加个 CNAME 就好了</li>
</ul>
</li>
<li>Jekyll 的自定制非常容易,基本就是个模版引擎</li>
</ul>
<hr />
<p>主题我直接 Downlosd 了 <a href="https://huangxuan.me/">Hux的博客主题</a> 的进行修改,简单粗暴,不过遇到了很多坑😂,好在都填完了。。。</p>
<p>本地调试环境需要 <code class="highlighter-rouge">gem install jekyll</code>,结果 rubygem 的源居然被墙了,<del>后来手动改成了我大淘宝的镜像源才成功</del>,淘宝的源已经<a href="https://gems.ruby-china.org/">停止维护</a>,换成了OSChina的源 <code class="highlighter-rouge">https://gems.ruby-china.org/</code>。</p>
<h2 id="后记">后记</h2>
<p>最后,感谢 Hux 提供的的 <a href="https://github.com/Huxpro/huxpro.github.io">Blog 主题</a></p>
<p>如果你恰好逛到了这里,希望你也能喜欢这个博客主题,感兴趣的话可以自己动手搭建一个。</p>
<p>—— BY 后记于 2017.2</p>
</description>
<pubDate>Sat, 04 Feb 2017 00:00:00 +0800</pubDate>
<link>http://localhost:4000/2017/02/04/Hello-2017/</link>
<guid isPermaLink="true">http://localhost:4000/2017/02/04/Hello-2017/</guid>
<category>生活</category>
</item>
<item>
<title>定时器 你真的会使用吗?</title>
<description><blockquote>
<p>定时器的使用是软件开发基础技能,用于延时执行或重复执行某些方法。我相信大部分人接触iOS的定时器都是从
<code class="highlighter-rouge">[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(action:) userInfo:nil repeats:YES]</code>这段代码开始的吧。</p>
</blockquote>
<blockquote>
<p>但是关于iOS定时器,你真的会用吗?</p>
</blockquote>
<h1 id="ios定时器">iOS定时器</h1>
<p>首先来介绍iOS中的定时器</p>
<p>iOS中的定时器大致分为这几类:</p>
<ul>
<li><strong>NSTimer</strong></li>
<li><strong>CADisplayLink</strong></li>
<li><strong>GCD定时器</strong></li>
</ul>
<h3 id="nstimer">NSTimer</h3>
<h4 id="使用方法">使用方法</h4>
<p><strong>NSTime</strong>定时器是我们比较常使用的定时器,比较常使用的方法有两种:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
</code></pre>
</div>
<p>这两种方法都是创建一个定时器,区别是用<code class="highlighter-rouge">timerWithTimeInterval:</code>方法创建的定时器需要手动加入RunLoop中。</p>
<div class="highlighter-rouge"><pre class="highlight"><code>// 创建NSTimer对象
NSTimer *timer = [NSTimer timerWithTimeInterval:3 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
// 加入RunLoop中
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
</code></pre>
</div>
<p>需要<strong>注意</strong>的是: <code class="highlighter-rouge">UIScrollView</code> 滑动时执行的是 <code class="highlighter-rouge">UITrackingRunLoopMode</code>,<code class="highlighter-rouge">NSDefaultRunLoopMode</code>被挂起,会导致定时器失效,等恢复为<strong>滑动结束</strong>时才恢复定时器。其原因可以查看我这篇<a href="http://www.jianshu.com/p/c4f552ceda63">《Objective-C RunLoop 详解》</a>中的 “RunLoop 的 Mode“章节,有详细的介绍。</p>
<p>举个例子:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>- (void)startTimer{
NSTimer *UIScrollView = [NSTimer timerWithTimeInterval:0.5 target:self selector:@selector(action:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
}
- (void)action:(NSTimer *)sender {
static int i = 0;
NSLog(@"NSTimer: %d",i);
i++;
}
</code></pre>
</div>
<p>将<code class="highlighter-rouge">timer</code>添加到<strong>NSDefaultRunLoopMode</strong>中,没0.5秒打印一次,然后滑动<code class="highlighter-rouge">UIScrollView</code>.</p>
<p>打印台输出:</p>
<p><img src="http://ww1.sinaimg.cn/large/006tNc79gw1farbzzwcevj30ci04ljtm.jpg" alt="" /></p>
<p>可以看出在滑动<code class="highlighter-rouge">UIScrollView</code>时,定时器被暂停了。</p>
<p>所以如果需要定时器在 <code class="highlighter-rouge">UIScrollView</code> 拖动时也不影响的话,有两种解决方法</p>
<ol>
<li>
<p><strong>timer</strong>分别添加到 <code class="highlighter-rouge">UITrackingRunLoopMode</code> 和 <code class="highlighter-rouge">NSDefaultRunLoopMode</code>中</p>
<div class="highlighter-rouge"><pre class="highlight"><code>[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop mainRunLoop] addTimer:timer forMode: UITrackingRunLoopMode];
</code></pre>
</div>
</li>
<li>
<p>直接将<strong>timer</strong>添加到<code class="highlighter-rouge">NSRunLoopCommonModes</code> 中:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>[[NSRunLoop mainRunLoop] addTimer:timer forMode: NSRunLoopCommonModes];
</code></pre>
</div>
</li>
</ol>
<p>但并不是都<strong>timer</strong>所有的需要在滑动<code class="highlighter-rouge">UIScrollView</code>时继续执行,比如使用<strong>NSTimer</strong>完成的帧动画,滑动<code class="highlighter-rouge">UIScrollView</code>时就可以停止帧动画,保证滑动的流程性。</p>
<p>若没有特殊要求的话,一般使用第二种方法创建完<strong>timer</strong>,会自动添加到<code class="highlighter-rouge">NSDefaultRunLoopMode</code>中去执行,也是平时最常用的方法。</p>
<div class="highlighter-rouge"><pre class="highlight"><code>NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(action:) userInfo:nil repeats:YES];
</code></pre>
</div>
<p>参数:</p>
<p><code class="highlighter-rouge">TimeInterval</code>:延时时间</p>
<p><code class="highlighter-rouge">target</code>:目标对象,一般就是<code class="highlighter-rouge">self</code>本身</p>
<p><code class="highlighter-rouge">selector</code>:执行方法</p>
<p><code class="highlighter-rouge">userInfo</code>:传入信息</p>
<p><code class="highlighter-rouge">repeats</code>:是否重复执行</p>
<p>以上创建的定时器,若<code class="highlighter-rouge">repeats</code>参数设为<code class="highlighter-rouge">NO</code>,执行一次后就会被释放掉;</p>
<p>若<code class="highlighter-rouge">repeats</code>参数设为<code class="highlighter-rouge">YES</code>重复执行时,必须手动关闭,否则定时器不会释放(停止)。</p>
<p>释放方法:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>// 停止定时器
[timer invalidate];
</code></pre>
</div>
<p>实际开发中,我们会将<code class="highlighter-rouge">NSTimer</code>对象设置为属性,这样方便释放。</p>
<p><strong>iOS10.0</strong> 推出了两个新的API,与上面的方法相比,<code class="highlighter-rouge">selector</code>换成Block回调以、减少传入的参数(那几个参数真是鸡肋)。不过开发中一般需要适配低版本,还是尽量使用上面的方法吧。</p>
<div class="highlighter-rouge"><pre class="highlight"><code>+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
</code></pre>
</div>
<h4 id="特点">特点</h4>
<ul>
<li>
<p><strong>必须加入Runloop</strong></p>
<p>上面不管使用哪种方法,实际最后都会加入RunLoop中执行,区别就在于是否手动加入而已。</p>
</li>
<li>
<p><strong>存在延迟</strong></p>
<p>不管是一次性的还是周期性的timer的实际触发事件的时间,都会与所加入的RunLoop和RunLoop Mode有关,如果此RunLoop正在执行一个连续性的运算,timer就会被延时出发。重复性的timer遇到这种情况,如果延迟超过了一个周期,则会在延时结束后立刻执行,并按照之前指定的周期继续执行,这个延迟时间大概为50-100毫秒.</p>
<p>所以NSTimer不是绝对准确的,而且中间耗时或阻塞错过下一个点,那么下一个点就pass过去了.</p>
</li>
<li>
<p><strong>UIScrollView滑动会暂停计时</strong></p>
<p>添加到<code class="highlighter-rouge">NSDefaultRunLoopMode</code>的 <code class="highlighter-rouge">timer</code> 在 <code class="highlighter-rouge">UIScrollView</code>滑动时会暂停,若不想被<code class="highlighter-rouge">UIScrollView</code>滑动影响,需要将 <code class="highlighter-rouge">timer</code> 添加再到 <code class="highlighter-rouge">UITrackingRunLoopMode</code> 或 直接添加到<code class="highlighter-rouge">NSRunLoopCommonModes</code> 中</p>
</li>
</ul>
<h2 id="cadisplaylink">CADisplayLink</h2>
<p>CADisplayLink官方介绍:</p>
<blockquote>
<p>A CADisplayLink object is a timer object that allows your application to synchronize its drawing to the refresh rate of the display</p>
</blockquote>
<p><strong>CADisplayLink</strong>对象是一个和屏幕刷新率同步的定时器对象。每当屏幕显示内容刷新结束的时候,runloop就会向CADisplayLink指定的<code class="highlighter-rouge">target</code>发送一次指定的<code class="highlighter-rouge">selector</code>消息, CADisplayLink类对应的 <code class="highlighter-rouge">selector</code> 就会被调用一次。</p>
<p>从原理上可以看出,CADisplayLink适合做界面的不停重绘,比如视频播放的时候需要不停地获取下一帧用于界面渲染,或者做动画。</p>
<h4 id="使用方法-1">使用方法</h4>
<p>创建:</p>
<div class="highlighter-rouge"><pre class="highlight"><code><span class="k">@property</span> <span class="p">(</span><span class="n">nonatomic</span><span class="p">,</span> <span class="n">strong</span><span class="p">)</span> <span class="n">CADisplayLink</span> <span class="o">*</span><span class="n">displayLink</span><span class="p">;</span>
<span class="n">self</span><span class="p">.</span><span class="n">displayLink</span> <span class="o">=</span> <span class="p">[</span><span class="n">CADisplayLink</span> <span class="nf">displayLinkWithTarget</span><span class="p">:</span><span class="n">self</span> <span class="nf">selector</span><span class="p">:</span><span class="k">@selector</span><span class="p">(</span><span class="n">handleDisplayLink</span><span class="o">:</span><span class="p">)];</span>
<span class="c1">// 每隔1帧调用一次
</span><span class="n">self</span><span class="p">.</span><span class="n">displayLink</span><span class="p">.</span><span class="n">frameInterval</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">displayLink</span> <span class="nf">addToRunLoop</span><span class="p">:[</span><span class="n">NSRunLoop</span> <span class="nf">currentRunLoop</span><span class="p">]</span> <span class="nf">forMode</span><span class="p">:</span><span class="n">NSDefaultRunLoopMode</span><span class="p">];</span>
</code></pre>
</div>
<p>释放方法:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>[self.displayLink invalidate];
self.displayLink = nil;
</code></pre>
</div>
<p>当把<strong>CADisplayLink</strong>对象添加到runloop中后,<code class="highlighter-rouge">selector</code>就能被周期性调用,类似于重复的NSTimer被启动了;执行<code class="highlighter-rouge">invalidate</code>操作时,CADisplayLink对象就会从runloop中移除,<code class="highlighter-rouge">selector</code>调用也随即停止,类似于NSTimer的<code class="highlighter-rouge">invalidate</code>方法。</p>
<p><strong>CADisplayLink</strong>中有两个重要的属性:</p>
<ul>
<li>
<p><strong>frameInterval</strong></p>
<p>NSInteger类型的值,用来设置间隔多少帧调用一次<code class="highlighter-rouge">selector</code>方法,默认值是1,即每帧都调用一次。</p>
</li>
<li>
<p><strong>duration</strong></p>
<p><code class="highlighter-rouge">CFTimeInterval</code>值为<code class="highlighter-rouge">readOnly</code>,表示两次屏幕刷新之间的时间间隔。需要注意的是,该属性在<code class="highlighter-rouge">targe</code>t的<code class="highlighter-rouge">selector</code>被首次调用以后才会被赋值。<code class="highlighter-rouge">selector</code>的调用间隔时间计算方式是:<strong>调用间隔时间 = duration × frameInterval</strong>。</p>
</li>
</ul>
<h4 id="特点-1">特点</h4>
<ul>
<li>
<p><strong>刷新频率固定</strong></p>
<p>正常情况iOS设备的屏幕刷新频率是固定<strong>60Hz</strong>,如果CPU过于繁忙,无法保证屏幕60次/秒的刷新率,就会导致跳过若干次调用回调方法的机会,跳过次数取决CPU的忙碌程度。</p>
</li>
<li>
<p><strong>屏幕刷新时调用</strong></p>
<p>CADisplayLink在正常情况下会在每次刷新结束都被调用,精确度相当高。但如果调用的方法比较耗时,超过了屏幕刷新周期,就会导致跳过若干次回调调用机会</p>
</li>
<li>
<p><strong>适合做界面渲染</strong></p>
<p>CADisplayLink可以确保系统渲染每一帧的时候我们的方法都被调用,从而保证了动画的流畅性。</p>
</li>
</ul>
<h2 id="gcd定时器">GCD定时器</h2>
<p><strong>GCD定时器</strong>和NSTimer是不一样的,NSTimer受RunLoop影响,但是GCD的定时器不受影响,因为通过源码可知RunLoop也是基于GCD的实现的,所以GCD定时器有非常高的精度。关于GCD的使用可一看看<a href="http://www.cnblogs.com/pure/archive/2013/03/31/2977420.html">这篇博客</a>。</p>
<h4 id="使用方法-2">使用方法</h4>
<p>创建GCD定时器定时器的方法稍微比较复杂,看下面的代码:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>// 定时时间
int interval = 1;
// 创建全局队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 创建定时器
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
// 设置定时器 interval * NSEC_PER_SEC 定时间隔几秒
dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval * NSEC_PER_SEC, 0);
dispatch_source_set_event_handler(timer, ^{
dispatch_async(dispatch_get_main_queue(), ^{
// 需要执行的代码
});
});
// 开启定时器
dispatch_resume(timer);
// 关闭定时器
dispatch_source_cancel(timer);
</code></pre>
</div>
<h4 id="单次的延时调用">单次的延时调用</h4>
<p>NSObject中的<code class="highlighter-rouge">performSelector:withObject:afterDelay:</code>以及 <code class="highlighter-rouge">performSelector:withObject:afterDelay:inModes:</code> 这两个方法在调用的时候会设置当前 runloop 中 <code class="highlighter-rouge">timer</code> ,前者设置的 <code class="highlighter-rouge">timer</code> 在 <code class="highlighter-rouge">NSDefaultRunLoopMode</code> 运行,后者则可以指定 <strong>NSRunLoop</strong> 的 <code class="highlighter-rouge">mode</code> 来执行。我们上面介绍过 runloop 中 <code class="highlighter-rouge">timer</code> 在 <code class="highlighter-rouge">UITrackingRunLoopMode</code> 被挂起,就导致了代码就会一直等待 <code class="highlighter-rouge">timer</code> 的调度,解决办法在上面也有说明。</p>
<p>不过我们可以用另一套方案来解决这个问题,就是使用GCD中的 <code class="highlighter-rouge">dispatch_after</code> 来实现单次的延时调用:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self someMethod];
});
</code></pre>
</div>
<h4 id="循环调用">循环调用</h4>
<div class="highlighter-rouge"><pre class="highlight"><code>// 创建GCD定时器
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), 1.0 * NSEC_PER_SEC, 0); //每秒执行
// 事件回调
dispatch_source_set_event_handler(_timer, ^{
dispatch_async(dispatch_get_main_queue(), ^{
// 在主线程中实现需要的功能
}
}
});
// 开启定时器
dispatch_resume(_timer);
// 挂起定时器(dispatch_suspend 之后的 Timer,是不能被释放的!会引起崩溃)
dispatch_suspend(_timer);
// 关闭定时器
dispatch_source_cancel(_timer);
</code></pre>
</div>
<p>上面代码中要注意的是:</p>
<ol>
<li><code class="highlighter-rouge">dispatch_source_set_event_handler()</code>中的任务实在子线程中执行的,若需要回到主线程,要调用<code class="highlighter-rouge">dispatch_async(dispatch_get_main_queue(), ^{}</code>.
<ul>
<li><code class="highlighter-rouge">dispatch_source_set_timer</code> 中第二个参数,当我们使用 <code class="highlighter-rouge">dispatch_time</code> 或者 <code class="highlighter-rouge">DISPATCH_TIME_NOW</code> 时,系统会使用默认时钟来进行计时。然而当系统休眠的时候,默认时钟是不走的,也就会导致计时器停止。使用 <code class="highlighter-rouge">dispatch_walltime </code> 可以让计时器按照真实时间间隔进行计时.</li>
<li>第三个参数, ` 1.0 * NSEC_PER_SEC` 为每秒执行一次,对应的还有毫秒,分秒,纳秒可以选择.</li>
</ul>
</li>
</ol>
<ul>
<li><code class="highlighter-rouge">dispatch_source_set_event_handler</code> 这个函数在执行完之后,block 会立马执行一遍,后面隔一定时间间隔再执行一次。而 <code class="highlighter-rouge">NSTimer</code> 第一次执行是到计时器触发之后。这也是和 <code class="highlighter-rouge">NSTimer</code> 之间的一个显著区别。</li>
<li>挂起(暂停)定时器, <code class="highlighter-rouge">dispatch_suspend</code> 之后的 <code class="highlighter-rouge">Timer</code>,不能被释放的,会引起崩溃.</li>
<li>创建的<code class="highlighter-rouge">timer</code>一定要有<code class="highlighter-rouge">dispatch_suspend(_timer)</code>或<code class="highlighter-rouge">dispatch_source_cancel(_timer)</code>这两句话来指定出口,否则定时器将不执行,若我们想无限循环可将 <code class="highlighter-rouge">dispatch_source_cancel(_timer)</code> 写在一句永不执行的<code class="highlighter-rouge">if</code>判断语句中。</li>
</ul>
<h2 id="使用场景">使用场景</h2>
<p>介绍完iOS中的各种定时器,接下来我们来说说这几种定时器在开发中的几种用法。
###短信重发倒计时</p>
<p>短信倒计时使我们登录注册常用的功能,一般设置为60s,实现方法如下:</p>
<div class="highlighter-rouge"><pre class="highlight"><code><span class="c1">// 计时时间
</span><span class="k">@property</span> <span class="p">(</span><span class="n">nonatomic</span><span class="p">,</span> <span class="n">assign</span><span class="p">)</span> <span class="kt">int</span> <span class="n">timeout</span><span class="p">;</span>
<span class="cm">/** 开启倒计时 */</span>
<span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="n">startCountdown</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">_timeout</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">_timeout</span> <span class="o">=</span> <span class="mi">60</span><span class="p">;</span>
<span class="c1">// GCD定时器
</span> <span class="n">dispatch_queue_t</span> <span class="n">queue</span> <span class="o">=</span> <span class="n">dispatch_get_global_queue</span><span class="p">(</span><span class="n">DISPATCH_QUEUE_PRIORITY_DEFAULT</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">dispatch_source_t</span> <span class="n">_timer</span> <span class="o">=</span> <span class="n">dispatch_source_create</span><span class="p">(</span><span class="n">DISPATCH_SOURCE_TYPE_TIMER</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">queue</span><span class="p">);</span>
<span class="n">dispatch_source_set_timer</span><span class="p">(</span><span class="n">_timer</span><span class="p">,</span> <span class="n">dispatch_walltime</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="mi">1</span><span class="p">.</span><span class="mi">0</span> <span class="o">*</span> <span class="n">NSEC_PER_SEC</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="c1">//每秒执行
</span>
<span class="n">dispatch_source_set_event_handler</span><span class="p">(</span><span class="n">_timer</span><span class="p">,</span> <span class="o">^</span><span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">_timeout</span> <span class="o">&lt;=</span> <span class="mi">0</span> <span class="p">){</span><span class="c1">// 倒计时结束
</span>
<span class="c1">// 关闭定时器
</span> <span class="n">dispatch_source_cancel</span><span class="p">(</span><span class="n">_timer</span><span class="p">);</span>
<span class="n">dispatch_async</span><span class="p">(</span><span class="n">dispatch_get_main_queue</span><span class="p">(),</span> <span class="o">^</span><span class="p">{</span>
<span class="c1">//设置界面的按钮显示 根据自己需求设置
</span> <span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">sendMsgBtn</span> <span class="nf">setTitle</span><span class="p">:</span><span class="s">@"发送"</span> <span class="nf">forState</span><span class="p">:</span><span class="n">UIControlStateNormal</span><span class="p">];</span>
<span class="n">self</span><span class="p">.</span><span class="n">sendMsgBtn</span><span class="p">.</span><span class="n">enabled</span> <span class="o">=</span> <span class="nb">YES</span><span class="p">;</span>
<span class="p">});</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span><span class="c1">// 倒计时中
</span>
<span class="c1">// 显示倒计时结果
</span>
<span class="n">NSString</span> <span class="o">*</span><span class="n">strTime</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSString</span> <span class="nf">stringWithFormat</span><span class="p">:</span><span class="s">@"重发(%.2d)"</span><span class="p">,</span> <span class="n">_timeout</span><span class="p">];</span>
<span class="n">dispatch_async</span><span class="p">(</span><span class="n">dispatch_get_main_queue</span><span class="p">(),</span> <span class="o">^</span><span class="p">{</span>
<span class="c1">//设置界面的按钮显示 根据自己需求设置
</span>
<span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">sendMsgBtn</span> <span class="nf">setTitle</span><span class="p">:[</span><span class="n">NSString</span> <span class="nf">stringWithFormat</span><span class="p">:</span><span class="s">@"%@"</span><span class="p">,</span><span class="n">strTime</span><span class="p">]</span> <span class="nf">forState</span><span class="p">:</span><span class="n">UIControlStateNormal</span><span class="p">];</span>
<span class="n">self</span><span class="p">.</span><span class="n">sendMsgBtn</span><span class="p">.</span><span class="n">enabled</span> <span class="o">=</span> <span class="nb">NO</span><span class="p">;</span>
<span class="p">});</span>
<span class="n">_timeout</span><span class="o">--</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="c1">// 开启定时器
</span> <span class="n">dispatch_resume</span><span class="p">(</span><span class="n">_timer</span><span class="p">);</span>
<span class="p">}</span>
</code></pre>
</div>
<p>在上面代码中,我们设置了一个60s循环倒计时,当我们向服务器获取短信验证码成功时 调用该方法开始倒计时。每秒刷新按钮的倒计时数,倒计时结束时再将按钮 <code class="highlighter-rouge">Title</code> 恢复为“发送”.</p>
<p>有一点需要注意的是,按钮的样式要设置为 <strong>UIButtonTypeCustom</strong>,否则会出现刷新 <code class="highlighter-rouge">Title</code> 时闪烁.</p>
<p>我们可以把这个方法封装一下,方便调用,否则在控制器中写这么一大段代码确实也不优雅。</p>
<p>效果如下:</p>
<p><img src="http://ww3.sinaimg.cn/large/006tNc79jw1faspxkoemhj30ci0m8mxy.jpg" alt="" /></p>
<p><a href="https://github.com/qiubaiying/BYTimer">代码的gitHub链接</a></p>
<h3 id="每个几分钟向服务器发送数据">每个几分钟向服务器发送数据</h3>
<p>在有定位服务的APP中,我们需要每个一段时间将定位数据发送到服务器,比如每5s定位一次每隔5分钟将再统一将数据发送服务器,这样会处理比较省电。
一般程序进入后台时,定时器会停止,但是在定位APP中,需要持续进行定位,APP在后台时依旧可以运行,所以在后台定时器也是可以运行的。</p>
<p>注:关于iOS后台常驻,可以查看<a href="http://waitingyuan.blog.163.com/blog/static/2155781652014111133150534/">这篇博客</a></p>
<p>在使用GCD定时的时候发现GCD定时器也可以在后代运行,创建方法同上面的短信倒计时.</p>
<p>这里我们使用<strong>NSTimer</strong>来创建一个每个5分钟执行一次的定时器.</p>
<div class="highlighter-rouge"><pre class="highlight"><code><span class="cp">#import &lt;Foundation/Foundation.h&gt;
</span>
<span class="k">typedef</span> <span class="kt">void</span><span class="p">(</span><span class="o">^</span><span class="n">TimerBlock</span><span class="p">)();</span>
<span class="k">@interface</span> <span class="nc">BYTimer</span> <span class="p">:</span> <span class="nc">NSObject</span>
<span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">startTimerWithBlock</span><span class="p">:(</span><span class="n">TimerBlock</span><span class="p">)</span><span class="nv">timerBlock</span><span class="p">;</span>
<span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="n">stopTimer</span><span class="p">;</span>
<span class="k">@end</span>
</code></pre>
</div>
<div class="highlighter-rouge"><pre class="highlight"><code><span class="cp">#import "BYTimer.h"
</span>
<span class="k">@interface</span> <span class="nc">BYTimer</span> <span class="p">()</span>
<span class="k">@property</span> <span class="p">(</span><span class="n">nonatomic</span><span class="p">,</span> <span class="n">strong</span><span class="p">)</span> <span class="n">NSTimer</span> <span class="o">*</span><span class="n">timer</span><span class="p">;</span>
<span class="k">@property</span> <span class="p">(</span><span class="n">nonatomic</span><span class="p">,</span> <span class="n">strong</span><span class="p">)</span> <span class="n">TimerBlock</span> <span class="n">timerBlock</span><span class="p">;</span>
<span class="k">@end</span>
<span class="k">@implementation</span> <span class="nc">BYTimer</span>
<span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">startTimerWithBlock</span><span class="p">:(</span><span class="n">TimerBlock</span><span class="p">)</span><span class="nv">timerBlock</span> <span class="p">{</span>
<span class="n">self</span><span class="p">.</span><span class="n">timer</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSTimer</span> <span class="nf">timerWithTimeInterval</span><span class="p">:</span><span class="mi">300</span> <span class="nf">target</span><span class="p">:</span><span class="n">self</span> <span class="n">selector</span><span class="o">:</span><span class="k">@selector</span><span class="p">(</span><span class="n">_timerAction</span><span class="p">)</span> <span class="n">userInfo</span><span class="o">:</span><span class="nb">nil</span> <span class="n">repeats</span><span class="o">:</span><span class="nb">YES</span><span class="p">];</span>
<span class="p">[[</span><span class="n">NSRunLoop</span> <span class="nf">mainRunLoop</span><span class="p">]</span> <span class="nf">addTimer</span><span class="p">:</span><span class="n">self</span><span class="p">.</span><span class="n">timer</span> <span class="nf">forMode</span><span class="p">:</span><span class="n">NSRunLoopCommonModes</span><span class="p">];</span>
<span class="n">_timerBlock</span> <span class="o">=</span> <span class="n">timerBlock</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="n">_timerAction</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">self</span><span class="p">.</span><span class="n">timerBlock</span><span class="p">)</span> <span class="p">{</span>
<span class="n">self</span><span class="p">.</span><span class="n">timerBlock</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="o">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="n">stopTimer</span> <span class="p">{</span>
<span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">timer</span> <span class="nf">invalidate</span><span class="p">];</span>
<span class="p">}</span>
<span class="k">@end</span>
</code></pre>
</div>
<p>该接口的实现很简单,就是<strong>NSTimer</strong>创建了一个300s执行一次的定时器,但是要注意定时器需要加入<code class="highlighter-rouge">NSRunLoopCommonModes</code>中。</p>
<p>最后,要使定时器在后台能运行,app就需要在<a href="http://waitingyuan.blog.163.com/blog/static/2155781652014111133150534/">后台常驻</a>。</p>
</description>
<pubDate>Tue, 13 Dec 2016 00:00:00 +0800</pubDate>