-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
1932 lines (872 loc) · 145 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!doctype html>
<html class="theme-next pisces use-motion" lang="zh-Hans">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />
<link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />
<link href="/css/main.css?v=5.1.0" rel="stylesheet" type="text/css" />
<meta name="keywords" content="Hexo, NexT" />
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.1.0" />
<meta property="og:type" content="website">
<meta property="og:title" content="lxian's Blog">
<meta property="og:url" content="http://lxian2.space/index.html">
<meta property="og:site_name" content="lxian's Blog">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="lxian's Blog">
<script type="text/javascript" id="hexo.configurations">
var NexT = window.NexT || {};
var CONFIG = {
root: '/',
scheme: 'Pisces',
sidebar: {"position":"left","display":"post"},
fancybox: true,
motion: true,
duoshuo: {
userId: '0',
author: '博主'
},
algolia: {
applicationID: '',
apiKey: '',
indexName: '',
hits: {"per_page":10},
labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
}
};
</script>
<link rel="canonical" href="http://lxian2.space/"/>
<title> lxian's Blog </title>
</head>
<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-68852515-1', 'auto');
ga('send', 'pageview');
</script>
<div class="container one-collumn sidebar-position-left
page-home
">
<div class="headband"></div>
<header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-meta ">
<div class="custom-logo-site-title">
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<span class="site-title">lxian's Blog</span>
<span class="logo-line-after"><i></i></span>
</a>
</div>
<p class="site-subtitle"></p>
</div>
<div class="site-nav-toggle">
<button>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
</button>
</div>
<nav class="site-nav">
<ul id="menu" class="menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section">
<i class="menu-item-icon fa fa-fw fa-home"></i> <br />
首页
</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives" rel="section">
<i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
归档
</a>
</li>
<li class="menu-item menu-item-tags">
<a href="/tags" rel="section">
<i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
标签
</a>
</li>
</ul>
</nav>
</div>
</header>
<main id="main" class="main">
<div class="main-inner">
<div class="content-wrap">
<div id="content" class="content">
<section id="posts" class="posts-expand">
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<link itemprop="mainEntityOfPage" href="http://lxian2.space/2016/12/31/简单总结pep333/">
<span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="lxian2">
<meta itemprop="description" content="">
<meta itemprop="image" content="https://avatars2.githubusercontent.com/u/3442641?v=3&s=460">
</span>
<span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="lxian's Blog">
<span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject">
<img style="display:none;" itemprop="url image" alt="lxian's Blog" src="">
</span>
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/12/31/简单总结pep333/" itemprop="url">
简单总结pep333
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="Post created" itemprop="dateCreated datePublished" datetime="2016-12-31T17:24:28+08:00">
2016-12-31
</time>
</span>
<span class="post-comments-count">
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-comment-o"></i>
</span>
<a href="/2016/12/31/简单总结pep333/#comments" itemprop="discussionUrl">
<span class="post-comments-count ds-thread-count" data-thread-key="2016/12/31/简单总结pep333/" itemprop="commentCount"></span>
</a>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h4 id="应用端"><a href="#应用端" class="headerlink" title="应用端"></a>应用端</h4><p>提供一个callable 的object. 它应当接受两个参数<code>environ</code>, <code>start_response</code>。并将response body 以一个iterable object 的形式return。</p>
<ol>
<li>environ<br>包含当前request的各种参数</li>
<li>start_reponse<br>一个callable object, 接受<code>status</code>,<code>response_headers</code>和 <code>exc_info</code>.<br><code>exc_info</code> 是应用将错误传递给网关端用的。<br><code>start_response</code> 作用是写reponse header,所以需在retrun之前调用</li>
<li>return - iterable response body<br>服务器端会读完它并将其写入response</li>
</ol>
<h4 id="服务器端"><a href="#服务器端" class="headerlink" title="服务器端"></a>服务器端</h4><p>每次request 调用应用端端callable 并传入相应的参数。在应用端调用<code>start_response</code>之后,写header,并在应用端返回后,发送header和body</p>
<h4 id="中间件"><a href="#中间件" class="headerlink" title="中间件"></a>中间件</h4><p>对应用端看来它是服务器端,服务器端看来它是应用端。也就是说它需要同时实现应用端和服务器端。<br>所以它需要</p>
<ol>
<li>能接收一个应用端程序,并实现自己的<code>start_response</code>,将服务器端的<code>start_response</code>封装进去</li>
<li>callable 并能接收接收<code>environ</code>, <code>start_response</code>,</li>
<li>在服务器端调用自己的时候,调用应用程序,并且传入自己的<code>start_response</code></li>
</ol>
<p>由上面可以看出,中间件可以在两个地方实现自己的功能</p>
<ol>
<li>在被服务器端调用的时候,可以改写<code>environ</code></li>
<li>在自己封装的<code>start_response</code> 中,可以改写从应用端得到的<code>status</code>, <code>response_headers</code></li>
<li>在应用端返回之后,可以改写应用端返回的reponse body</li>
</ol>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<link itemprop="mainEntityOfPage" href="http://lxian2.space/2016/07/18/GCD-Overview/">
<span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="lxian2">
<meta itemprop="description" content="">
<meta itemprop="image" content="https://avatars2.githubusercontent.com/u/3442641?v=3&s=460">
</span>
<span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="lxian's Blog">
<span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject">
<img style="display:none;" itemprop="url image" alt="lxian's Blog" src="">
</span>
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/07/18/GCD-Overview/" itemprop="url">
GCD Overview
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="Post created" itemprop="dateCreated datePublished" datetime="2016-07-18T12:56:55+08:00">
2016-07-18
</time>
</span>
<span class="post-comments-count">
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-comment-o"></i>
</span>
<a href="/2016/07/18/GCD-Overview/#comments" itemprop="discussionUrl">
<span class="post-comments-count ds-thread-count" data-thread-key="2016/07/18/GCD-Overview/" itemprop="commentCount"></span>
</a>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>总结下 GCD.</p>
<h4 id="Basics"><a href="#Basics" class="headerlink" title="Basics"></a>Basics</h4><p>CGD 是对线程的抽象。将线程管理交给系统实现,程序员只需要将想执行的任务加入到相应的队列中。</p>
<p>只有global queue 会被调度运行。当创建自己的queue 的时候,实际上会被set target 到global queue 去,custome queue 将要执行的 block 交给 global queue 执行。(存疑,只在一本书上看到这样的描述)</p>
<p>Concurrent Disptach Queue 会由系统来决定应当生成的线程数。而 Serial Dispatch Queue 每创建一条都会创建一条新线程。(大量生成 Serial Queue 会消耗大量内存)</p>
<p>iOS 6.0 之后 GCD 已经加入 ARC, 无需手动释放。</p>
<h4 id="Set-target"><a href="#Set-target" class="headerlink" title="Set target"></a>Set target</h4><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">dispatch_set_target(queueA, queueB);</div></pre></td></tr></table></figure>
<p>queueA 将 block 传给 queueB 执行</p>
<h4 id="Suspend-amp-Resume"><a href="#Suspend-amp-Resume" class="headerlink" title="Suspend & Resume"></a>Suspend & Resume</h4><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">dispatch_suspend(queue);</div><div class="line">dispatch_resume(queue);</div></pre></td></tr></table></figure>
<p>queue 被 suspend 之后将停止执行队列中的block. (当前block会继续执行到结束)</p>
<h4 id="dispatch-barrier-async"><a href="#dispatch-barrier-async" class="headerlink" title="dispatch_barrier_async"></a>dispatch_barrier_async</h4><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">dispatch_async</span>(queue, ^{</div><div class="line"> <span class="comment">// read blocks one</span></div><div class="line">});</div><div class="line"></div><div class="line">dispatch_barrier_async(queue, ^{</div><div class="line"> <span class="comment">// write block</span></div><div class="line">});</div><div class="line"></div><div class="line"><span class="built_in">dispatch_async</span>(queue, ^{</div><div class="line"> <span class="comment">// read blocks two</span></div><div class="line">});</div></pre></td></tr></table></figure>
<p>dispatch_barrier_async 加入block 之前的 blocks 执行完毕后, 执行 barrier 加入的 block, 完成之后再执行之后加入的 block</p>
<p>case: read block 用普通的 dispatch_async, write block 用 dispatch_barrier_async。比如一个array,可以用这样的方法来保证其线程安全。</p>
<h4 id="dispatch-group"><a href="#dispatch-group" class="headerlink" title="dispatch group"></a>dispatch group</h4><p>将几个block group 起来,全部执行完后通知用户<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">dispatch_group_t group = dispatch_group_create();</div><div class="line"></div><div class="line">dispatch_group_async(group, queue, blockA);</div><div class="line">dispatch_group_async(group, queue, blockB);</div><div class="line"></div><div class="line"><span class="comment">// blockC will be executed after blockA and block B finishes</span></div><div class="line">dispatch_group_notify(group, queue, blockC);</div></pre></td></tr></table></figure></p>
<p>dispatch_group_wait 设置等待时间,到时间直接返回,若为0 则全部完成。设置 DISPATCH_TIME_FOREVER 永远等待,DISPTACH_TIME_NOW 立即返回。<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">long</span> result = dispatch_group_wait(group, time);</div><div class="line"><span class="keyword">if</span> (result == <span class="number">0</span>) {</div><div class="line"> <span class="comment">// all blocks finished executing</span></div><div class="line">} <span class="keyword">else</span> {</div><div class="line"> <span class="comment">// some blocks are not finished yet</span></div><div class="line">}</div></pre></td></tr></table></figure></p>
<h4 id="dispatch-apply"><a href="#dispatch-apply" class="headerlink" title="dispatch_apply"></a>dispatch_apply</h4><p>dispatch_sync 的复数版本<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// execute the block on queue 10 times, </span></div><div class="line"><span class="comment">// will block current thread until all blocks are finished</span></div><div class="line">dispatch_apply(<span class="number">10</span>, queue, ^(size_t index){</div><div class="line"> <span class="comment">// index of the executing times</span></div><div class="line">});</div></pre></td></tr></table></figure></p>
<h4 id="dispatch-semaphore"><a href="#dispatch-semaphore" class="headerlink" title="dispatch semaphore"></a>dispatch semaphore</h4><p>计数信号<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// create a semphore with initial count of 10</span></div><div class="line">dispatch_semaphore_t semaphore = dispatch_semaphore_create(<span class="number">10</span>);</div><div class="line"></div><div class="line"><span class="comment">// wait for the chance to reduce 1 to the semaphore</span></div><div class="line"><span class="keyword">long</span> result = dispatch_semaphore_wait(semaphore, time);</div><div class="line"></div><div class="line"><span class="comment">// perform some tasks...</span></div><div class="line"></div><div class="line"><span class="comment">// increacse one to semaphore</span></div><div class="line">dispatch_semaphore_signal(semaphore);</div></pre></td></tr></table></figure></p>
<h4 id="dispatch-once"><a href="#dispatch-once" class="headerlink" title="dispatch_once"></a>dispatch_once</h4><p>略</p>
<h4 id="dispatch-source"><a href="#dispatch-source" class="headerlink" title="dispatch source"></a>dispatch source</h4><h5 id="dispatch-source-data-add"><a href="#dispatch-source-data-add" class="headerlink" title="dispatch source data add"></a>dispatch source data add</h5><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line">dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD,</div><div class="line"> <span class="number">0</span>, <span class="number">0</span>, queue);</div><div class="line"></div><div class="line"><span class="comment">// add handler to the source </span></div><div class="line">__block <span class="keyword">long</span> totalComplete = <span class="number">0</span>;</div><div class="line">dispatch_source_set_event_handler(source, ^{</div><div class="line"> <span class="keyword">long</span> value = dispatch_source_get_data(source);</div><div class="line"> totalComplete += value;</div><div class="line">})</div><div class="line"></div><div class="line"><span class="comment">// created cource is in suspended status</span></div><div class="line"><span class="comment">// needs to be resumed</span></div><div class="line">dispatch_resume(source);</div><div class="line"></div><div class="line"><span class="comment">// sending data to the source</span></div><div class="line"><span class="built_in">dispatch_async</span>(queue, ^{</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span> ; i <= <span class="number">100</span>; i++) {</div><div class="line"> dispatch_source_merge_data(source, <span class="number">1</span>);</div><div class="line"> usleep(<span class="number">200000</span>);</div><div class="line"> }</div><div class="line">})</div></pre></td></tr></table></figure>
<p>注意不可发送0 或者 复数</p>
<h5 id="dispatch-timer"><a href="#dispatch-timer" class="headerlink" title="dispatch timer"></a>dispatch timer</h5><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">void</span> dispatch_source_set_timer( dispatch_source_t source, dispatch_time_t start, uint64_t interval, uint64_t leeway);</div></pre></td></tr></table></figure>
<p>start - start after the start interval<br>interval - execution interval. the handler will be called with after the first execution repeately with the interval. set to DISPATCH_TIME_FOREVER if you want to perform it only once. (use dispatch_after if you want to perform some task after a delay only once)<br>leeway - the time allowed for delay. used a hint to the system<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">dispatch_queue_t</span> queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, <span class="number">0</span>);</div><div class="line"> dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, <span class="number">0</span>, <span class="number">0</span>, queue);</div><div class="line"> dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, <span class="number">5</span> * <span class="built_in">NSEC_PER_SEC</span>), <span class="number">1</span> * <span class="built_in">NSEC_PER_SEC</span>, <span class="number">1</span> * <span class="built_in">NSEC_PER_SEC</span>);</div><div class="line"> dispatch_source_set_event_handler(timer, ^{</div><div class="line"> <span class="comment">// perform some tasks</span></div><div class="line"> });</div><div class="line"> </div><div class="line"> </div><div class="line"> <span class="comment">// to cancel the timer after 10 seconds</span></div><div class="line"> <span class="built_in">dispatch_queue_t</span> q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, <span class="number">0</span>);</div><div class="line"> dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<span class="number">10</span> * <span class="built_in">NSEC_PER_SEC</span>)), dispatch_get_main_queue(), ^{</div><div class="line"> dispatch_cancel(timer);</div><div class="line"> });</div></pre></td></tr></table></figure></p>
<h5 id="Queue-sepcific-data"><a href="#Queue-sepcific-data" class="headerlink" title="Queue sepcific data"></a>Queue sepcific data</h5><p>Similiar to the Associated Object. Assign a key-value pair to a queue. A release function is required.<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">static</span> <span class="keyword">char</span> key;</div><div class="line"><span class="built_in">CFStringRef</span> *value = <span class="built_in">CFSTR</span>(<span class="string">"some string"</span>);</div><div class="line">dispatch_queue_set_specific(queue, </div><div class="line"> &key, </div><div class="line"> (<span class="keyword">void</span>*)value, </div><div class="line"> (dispatch_function_t)<span class="built_in">CFRelease</span>); </div><div class="line"> </div><div class="line"> <span class="built_in">CFStringRef</span> *str = dispatch_get_specific(&key);</div></pre></td></tr></table></figure></p>
<p>如果找不到key, 会向target queue 查询。</p>
<p>例子<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">dispatch_queue_set_specific(q, &key, (__bridge <span class="keyword">void</span>*)q, <span class="literal">NULL</span>);</div></pre></td></tr></table></figure></p>
<p>因为dispatch_get_current_queue 可能会造成死锁,如下,get current queue 检查为当前queue 为queue B, 所以调用 dispatch_sync(queueA, …), 造成死锁(因为最外面还套一个 dispatch_sync(queueA, …))<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// a 'not' safe sync</span></div><div class="line"><span class="keyword">void</span> dispatch_sync_safe(<span class="built_in">dispatch_queue_t</span> queue, dispatch_block_t block) {</div><div class="line"> <span class="keyword">if</span> (dispatch_get_current_queue() == queue) {</div><div class="line"> block();</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="built_in">dispatch_sync</span>(queue, block);</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="built_in">dispatch_sync</span>(queueA, ^{</div><div class="line"> <span class="built_in">dispatch_sync</span>(queueB, ^{</div><div class="line"> dispatch_sync_safe(queueA, ^{</div><div class="line"> <span class="comment">// some tasks...</span></div><div class="line"> })</div><div class="line"> });</div><div class="line">});</div></pre></td></tr></table></figure></p>
<p>上面的dispatch_sync_safe 重入,导致deadlock</p>
<p>解决方法:<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <span class="keyword">char</span> sQueueTagKey;</div><div class="line"></div><div class="line"><span class="keyword">void</span> RNQueueTag(<span class="built_in">dispatch_queue_t</span> q) {</div><div class="line"> <span class="comment">// Make q point to itself by assignment.</span></div><div class="line"> <span class="comment">// This doesn't retain, but it can never dangle.</span></div><div class="line"> dispatch_queue_set_specific(q, &sQueueTagKey, (__bridge <span class="keyword">void</span>*)q, <span class="literal">NULL</span>);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="built_in">dispatch_queue_t</span> RNQueueCreateTagged(<span class="keyword">const</span> <span class="keyword">char</span> *label,</div><div class="line"> dispatch_queue_attr_t attr) {</div><div class="line"> <span class="built_in">dispatch_queue_t</span> q = dispatch_queue_create(label, attr);</div><div class="line"> RNQueueTag(q);</div><div class="line"> <span class="keyword">return</span> q;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="built_in">dispatch_queue_t</span> RNQueueGetCurrentTagged() {</div><div class="line"> <span class="keyword">return</span> (__bridge <span class="built_in">dispatch_queue_t</span>)dispatch_get_specific(&sQueueTagKey);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="built_in">BOOL</span> RNQueueCurrentIsTaggedQueue(<span class="built_in">dispatch_queue_t</span> q) {</div><div class="line"> <span class="keyword">return</span> (RNQueueGetCurrentTagged() == q);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="built_in">BOOL</span> RNQueueCurrentIsMainQueue() {</div><div class="line"> <span class="keyword">return</span> [<span class="built_in">NSThread</span> isMainThread];</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">void</span> RNQueueSafeDispatchSync(<span class="built_in">dispatch_queue_t</span> q, dispatch_block_t block) {</div><div class="line"> <span class="keyword">if</span> (RNQueueCurrentIsTaggedQueue(q)) {</div><div class="line"> block();</div><div class="line"> }</div><div class="line"> <span class="keyword">else</span> {</div><div class="line"> <span class="built_in">dispatch_sync</span>(q, block);</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>上面利用Queue sepcific data 会像target queue询问的特性来避免死锁。<br>不过只能应对这种只有两条queue 的情况,而且只能给最外面的queue 加上标签。(所以有啥用啊。。。)</p>
<h4 id="References"><a href="#References" class="headerlink" title="References"></a>References</h4><ol>
<li>iOS 7 Programming: Pushing the limit</li>
<li>Objective-C 高级编程</li>
</ol>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<link itemprop="mainEntityOfPage" href="http://lxian2.space/2016/01/23/CALayer-hittest-检索顺序/">
<span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="lxian2">
<meta itemprop="description" content="">
<meta itemprop="image" content="https://avatars2.githubusercontent.com/u/3442641?v=3&s=460">
</span>
<span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="lxian's Blog">
<span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject">
<img style="display:none;" itemprop="url image" alt="lxian's Blog" src="">
</span>
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/01/23/CALayer-hittest-检索顺序/" itemprop="url">
CALayer hittest 遍历顺序
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="Post created" itemprop="dateCreated datePublished" datetime="2016-01-23T12:36:54+08:00">
2016-01-23
</time>
</span>
<span class="post-comments-count">
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-comment-o"></i>
</span>
<a href="/2016/01/23/CALayer-hittest-检索顺序/#comments" itemprop="discussionUrl">
<span class="post-comments-count ds-thread-count" data-thread-key="2016/01/23/CALayer-hittest-检索顺序/" itemprop="commentCount"></span>
</a>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>CALayer 的 hittest 可以返回一个点所在点最远的layer。那么这个检查sublayer的顺序是怎么样的呢?<br>为了得到这个顺序,我们先用method swizzling 在 [CALayer hittest:] 里面加上一行打印当前layer 的代码<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">@implementation</span> <span class="title">CALayer</span>(<span class="title">hitTestTracking</span>)</span></div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="built_in">dispatch_once_t</span> hitTestTrackingOnceToken;</div><div class="line"></div><div class="line">+ (<span class="keyword">void</span>)load</div><div class="line">{</div><div class="line"> <span class="built_in">dispatch_once</span>(&hitTestTrackingOnceToken, ^{</div><div class="line"> Class <span class="keyword">class</span> = [<span class="keyword">self</span> <span class="keyword">class</span>];</div><div class="line"> SEL oriSelector = <span class="keyword">@selector</span>(hitTest:);</div><div class="line"> SEL swSelector = <span class="keyword">@selector</span>(xl_hitTest:);</div><div class="line"> </div><div class="line"> Method oriMethod = class_getInstanceMethod(<span class="keyword">class</span>, oriSelector);</div><div class="line"> Method swMethod = class_getInstanceMethod(<span class="keyword">class</span>, swSelector);</div><div class="line"> </div><div class="line"> <span class="built_in">BOOL</span> addedMethod = class_addMethod(<span class="keyword">class</span>, oriSelector, method_getImplementation(swMethod), method_getTypeEncoding(swMethod));</div><div class="line"> <span class="keyword">if</span> (addedMethod) {</div><div class="line"> class_replaceMethod(<span class="keyword">class</span>, swSelector, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod));</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> method_exchangeImplementations(oriMethod, swMethod);</div><div class="line"> }</div><div class="line"> });</div><div class="line">}</div><div class="line"></div><div class="line">- (<span class="built_in">CALayer</span> *)xl_hitTest:(<span class="built_in">CGPoint</span>)p {</div><div class="line"> <span class="built_in">CALayer</span> *hittedLayer = [<span class="keyword">self</span> xl_hitTest:p];</div><div class="line"> <span class="built_in">NSLog</span>(<span class="string">@"%@ %@ %@ hitted: %@"</span>, <span class="built_in">NSStringFromSelector</span>(_cmd), <span class="keyword">self</span>.name, <span class="keyword">self</span>, (hittedLayer == <span class="literal">nil</span> ? <span class="string">@"NO"</span> : <span class="string">@"YES"</span>));</div><div class="line"> <span class="keyword">return</span> hittedLayer;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>为了方便再加上打印sublayers的方法<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">- (<span class="keyword">void</span>)printSubLayers {</div><div class="line"> [<span class="keyword">self</span> printSubLayersWithNumberOfIndentation:<span class="number">0</span>];</div><div class="line">}</div><div class="line"></div><div class="line">- (<span class="keyword">void</span>)printSubLayersWithNumberOfIndentation:(<span class="built_in">NSInteger</span>)numberOfIndentation {</div><div class="line"> <span class="built_in">NSInteger</span> n = numberOfIndentation;</div><div class="line"> <span class="keyword">while</span> (n--) {</div><div class="line"> printf(<span class="string">"----"</span>);</div><div class="line"> }</div><div class="line"> printf(<span class="string">"%s %s\n"</span>, <span class="keyword">self</span>.name.UTF8String, <span class="keyword">self</span>.description.UTF8String);</div><div class="line"> <span class="keyword">for</span> (<span class="built_in">CALayer</span> *layer <span class="keyword">in</span> <span class="keyword">self</span>.sublayers) {</div><div class="line"> [layer printSubLayersWithNumberOfIndentation:numberOfIndentation + <span class="number">1</span>];</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>然后在view controller 随便创建一个view, 加入一些 layer 并调用 hittest 来进行<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div></pre></td><td class="code"><pre><div class="line">- (<span class="keyword">void</span>)viewDidLoad {</div><div class="line"> [<span class="keyword">super</span> viewDidLoad];</div><div class="line"> <span class="keyword">self</span>.layerView.layer.name = <span class="string">@"layer 0"</span>;</div><div class="line"> </div><div class="line"> <span class="built_in">CALayer</span> *layer1 = [<span class="built_in">CALayer</span> layer];</div><div class="line"> layer1.backgroundColor = [<span class="built_in">UIColor</span> grayColor].CGColor;</div><div class="line"> layer1.frame = <span class="keyword">self</span>.layerView.bounds;</div><div class="line"> layer1.name = <span class="string">@"layer 1"</span>;</div><div class="line"> </div><div class="line"> <span class="built_in">CALayer</span> *layer2 = [<span class="built_in">CALayer</span> layer];</div><div class="line"> layer2.frame = <span class="keyword">self</span>.layerView.bounds;</div><div class="line"> layer2.name = <span class="string">@"layer 2"</span>;</div><div class="line"> </div><div class="line"> <span class="built_in">CALayer</span> *layer3 = [<span class="built_in">CALayer</span> layer];</div><div class="line"> layer3.frame = <span class="built_in">CGRectMake</span>(<span class="number">100</span>, <span class="number">100</span>, <span class="number">5</span>, <span class="number">5</span>);</div><div class="line"> layer3.name = <span class="string">@"layer 3"</span>;</div><div class="line"> </div><div class="line"> <span class="built_in">CALayer</span> *layer11 = [<span class="built_in">CALayer</span> layer];</div><div class="line"> layer11.frame = <span class="keyword">self</span>.layerView.bounds;</div><div class="line"> layer11.name = <span class="string">@"layer 11"</span>;</div><div class="line"> </div><div class="line"> <span class="built_in">CALayer</span> *layer111 = [<span class="built_in">CALayer</span> layer];</div><div class="line"> layer111.frame = <span class="keyword">self</span>.layerView.bounds;</div><div class="line"> layer111.name = <span class="string">@"layer 111"</span>;</div><div class="line"> </div><div class="line"> <span class="built_in">CALayer</span> *layer12 = [<span class="built_in">CALayer</span> layer];</div><div class="line"> layer12.frame = <span class="keyword">self</span>.layerView.bounds;</div><div class="line"> layer12.name = <span class="string">@"layer 12"</span>;</div><div class="line"> </div><div class="line"> <span class="built_in">CALayer</span> *layer21 = [<span class="built_in">CALayer</span> layer];</div><div class="line"> layer21.frame = <span class="keyword">self</span>.layerView.bounds;</div><div class="line"> layer21.name = <span class="string">@"layer 21"</span>;</div><div class="line"> </div><div class="line"> <span class="built_in">CALayer</span> *layer31 = [<span class="built_in">CALayer</span> layer];</div><div class="line"> layer31.frame = <span class="built_in">CGRectMake</span>(<span class="number">100</span>, <span class="number">100</span>, <span class="number">5</span>, <span class="number">5</span>);</div><div class="line"> layer31.name = <span class="string">@"layer 31"</span>;</div><div class="line"> </div><div class="line"> [<span class="keyword">self</span>.layerView.layer addSublayer:layer1];</div><div class="line"> [<span class="keyword">self</span>.layerView.layer addSublayer:layer2];</div><div class="line"> [<span class="keyword">self</span>.layerView.layer addSublayer:layer3];</div><div class="line"> [layer1 addSublayer:layer11];</div><div class="line"> [layer1 addSublayer:layer12];</div><div class="line"> [layer11 addSublayer:layer111];</div><div class="line"> [layer2 addSublayer:layer21];</div><div class="line"> [layer3 addSublayer:layer31];</div><div class="line"> </div><div class="line"> <span class="built_in">CGPoint</span> p = [<span class="keyword">self</span>.view convertPoint:<span class="built_in">CGPointZero</span> fromView:<span class="keyword">self</span>.layerView];</div><div class="line"> [<span class="keyword">self</span>.layerView.layer printSubLayers];</div><div class="line"> <span class="built_in">CALayer</span> *layerHitted = [<span class="keyword">self</span>.layerView.layer hitTest:p];</div><div class="line"> <span class="built_in">NSLog</span>(<span class="string">@"layer hitted: %@ %@"</span>, layerHitted.name, layerHitted);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>得到如下输出:<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line">layer <span class="number">0</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be1e6e0</span>></div><div class="line">----layer <span class="number">1</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be26ef0</span>></div><div class="line">--------layer <span class="number">11</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be2c720</span>></div><div class="line">------------layer <span class="number">111</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be2c740</span>></div><div class="line">--------layer <span class="number">12</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be10e50</span>></div><div class="line">----layer <span class="number">2</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be2c6e0</span>></div><div class="line">--------layer <span class="number">21</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be10e70</span>></div><div class="line">----layer <span class="number">3</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be2c700</span>></div><div class="line">--------layer <span class="number">31</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be10e90</span>></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">31</span>:<span class="number">50.167</span> learnLayer[<span class="number">1966</span>:<span class="number">258255</span>] hitTest: layer <span class="number">111</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be2c740</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">31</span>:<span class="number">50.169</span> learnLayer[<span class="number">1966</span>:<span class="number">258255</span>] hitTest: layer <span class="number">11</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be2c720</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">31</span>:<span class="number">50.170</span> learnLayer[<span class="number">1966</span>:<span class="number">258255</span>] hitTest: layer <span class="number">12</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be10e50</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">31</span>:<span class="number">50.170</span> learnLayer[<span class="number">1966</span>:<span class="number">258255</span>] hitTest: layer <span class="number">1</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be26ef0</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">31</span>:<span class="number">50.170</span> learnLayer[<span class="number">1966</span>:<span class="number">258255</span>] hitTest: layer <span class="number">21</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be10e70</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">31</span>:<span class="number">50.170</span> learnLayer[<span class="number">1966</span>:<span class="number">258255</span>] hitTest: layer <span class="number">2</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be2c6e0</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">31</span>:<span class="number">50.171</span> learnLayer[<span class="number">1966</span>:<span class="number">258255</span>] hitTest: layer <span class="number">31</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be10e90</span>> hitted: <span class="literal">NO</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">31</span>:<span class="number">50.171</span> learnLayer[<span class="number">1966</span>:<span class="number">258255</span>] hitTest: layer <span class="number">3</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be2c700</span>> hitted: <span class="literal">NO</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">31</span>:<span class="number">50.172</span> learnLayer[<span class="number">1966</span>:<span class="number">258255</span>] hitTest: layer <span class="number">0</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be1e6e0</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">31</span>:<span class="number">50.172</span> learnLayer[<span class="number">1966</span>:<span class="number">258255</span>] layer hitted: layer <span class="number">21</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fc62be10e70</span>></div></pre></td></tr></table></figure></p>
<p>从上面我们可以看到,hittest 是用的DFS来遍历图层树,而且不存在短路设置(layer3, layer 31)(其实有短路的,当maskToBounds = YES 的时候就可以有短路了,会在接下来的部分里说明),所有的layer都会被检查一遍,但是最后返回的结果是在遍历中满足条件的最后一个layer (layer 21)。</p>
<p>接着试着将layer31 的位置改一下使得测试点处于layer31 里面:<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">layer31.frame = <span class="built_in">CGRectMake</span>(<span class="number">-100</span>, <span class="number">-100</span>, <span class="number">5</span>, <span class="number">5</span>);</div></pre></td></tr></table></figure></p>
<p>输出变成了:<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line">layer <span class="number">0</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e9b5b0</span>></div><div class="line">----layer <span class="number">1</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e90420</span>></div><div class="line">--------layer <span class="number">11</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e8b730</span>></div><div class="line">------------layer <span class="number">111</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e8b750</span>></div><div class="line">--------layer <span class="number">12</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e8df90</span>></div><div class="line">----layer <span class="number">2</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e06460</span>></div><div class="line">--------layer <span class="number">21</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e8dfb0</span>></div><div class="line">----layer <span class="number">3</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e8b680</span>></div><div class="line">--------layer <span class="number">31</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e90c50</span>></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">39</span>:<span class="number">13.951</span> learnLayer[<span class="number">2076</span>:<span class="number">266220</span>] hitTest: layer <span class="number">111</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e8b750</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">39</span>:<span class="number">13.952</span> learnLayer[<span class="number">2076</span>:<span class="number">266220</span>] hitTest: layer <span class="number">11</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e8b730</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">39</span>:<span class="number">13.953</span> learnLayer[<span class="number">2076</span>:<span class="number">266220</span>] hitTest: layer <span class="number">12</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e8df90</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">39</span>:<span class="number">13.953</span> learnLayer[<span class="number">2076</span>:<span class="number">266220</span>] hitTest: layer <span class="number">1</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e90420</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">39</span>:<span class="number">13.953</span> learnLayer[<span class="number">2076</span>:<span class="number">266220</span>] hitTest: layer <span class="number">21</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e8dfb0</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">39</span>:<span class="number">13.953</span> learnLayer[<span class="number">2076</span>:<span class="number">266220</span>] hitTest: layer <span class="number">2</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e06460</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">39</span>:<span class="number">13.953</span> learnLayer[<span class="number">2076</span>:<span class="number">266220</span>] hitTest: layer <span class="number">31</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e90c50</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">39</span>:<span class="number">13.953</span> learnLayer[<span class="number">2076</span>:<span class="number">266220</span>] hitTest: layer <span class="number">3</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e8b680</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">39</span>:<span class="number">13.953</span> learnLayer[<span class="number">2076</span>:<span class="number">266220</span>] hitTest: layer <span class="number">0</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e9b5b0</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">39</span>:<span class="number">13.954</span> learnLayer[<span class="number">2076</span>:<span class="number">266220</span>] layer hitted: layer <span class="number">31</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb920e90c50</span>></div></pre></td></tr></table></figure></p>
<p>最终的结果变成了layer31,从这里我们就可以知道为什么不存在简单的短路设置(如果当前图层的位置的大小不满足条件就不遍历其子图层)了,因为子图层的位置与父图层并不存在直接关系,一个不在父图层中的点仍可能在其子图层中。</p>
<p>让我们再来把layer3 的maskToBounds 设为 YES:<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">layer3.masksToBounds = <span class="literal">YES</span>;</div></pre></td></tr></table></figure></p>
<p>再跑一遍,输出又变了:<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line">layer <span class="number">0</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f1488f80</span>></div><div class="line">----layer <span class="number">1</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f1403cd0</span>></div><div class="line">--------layer <span class="number">11</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f1489a20</span>></div><div class="line">------------layer <span class="number">111</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f148b880</span>></div><div class="line">--------layer <span class="number">12</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f148b8a0</span>></div><div class="line">----layer <span class="number">2</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f14879e0</span>></div><div class="line">--------layer <span class="number">21</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f148b8c0</span>></div><div class="line">----layer <span class="number">3</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f1489a00</span>></div><div class="line">--------layer <span class="number">31</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f1489de0</span>></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">47</span>:<span class="number">55.756</span> learnLayer[<span class="number">2097</span>:<span class="number">272073</span>] hitTest: layer <span class="number">111</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f148b880</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">47</span>:<span class="number">55.757</span> learnLayer[<span class="number">2097</span>:<span class="number">272073</span>] hitTest: layer <span class="number">11</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f1489a20</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">47</span>:<span class="number">55.757</span> learnLayer[<span class="number">2097</span>:<span class="number">272073</span>] hitTest: layer <span class="number">12</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f148b8a0</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">47</span>:<span class="number">55.757</span> learnLayer[<span class="number">2097</span>:<span class="number">272073</span>] hitTest: layer <span class="number">1</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f1403cd0</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">47</span>:<span class="number">55.757</span> learnLayer[<span class="number">2097</span>:<span class="number">272073</span>] hitTest: layer <span class="number">21</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f148b8c0</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">47</span>:<span class="number">55.758</span> learnLayer[<span class="number">2097</span>:<span class="number">272073</span>] hitTest: layer <span class="number">2</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f14879e0</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">47</span>:<span class="number">55.758</span> learnLayer[<span class="number">2097</span>:<span class="number">272073</span>] hitTest: layer <span class="number">3</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f1489a00</span>> hitted: <span class="literal">NO</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">47</span>:<span class="number">55.772</span> learnLayer[<span class="number">2097</span>:<span class="number">272073</span>] hitTest: layer <span class="number">0</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f1488f80</span>> hitted: <span class="literal">YES</span></div><div class="line"><span class="number">2016</span><span class="number">-01</span><span class="number">-24</span> <span class="number">00</span>:<span class="number">47</span>:<span class="number">55.772</span> learnLayer[<span class="number">2097</span>:<span class="number">272073</span>] layer hitted: layer <span class="number">21</span> <<span class="built_in">CALayer</span>: <span class="number">0x7fb8f148b8c0</span>></div></pre></td></tr></table></figure></p>
<p>我们可以看到当开启maskToBounds 之后,便开始有短路了,layer31 不再出现在遍历树里面。</p>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<link itemprop="mainEntityOfPage" href="http://lxian2.space/2015/12/06/avfoundation-video-capture1/">
<span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="lxian2">
<meta itemprop="description" content="">
<meta itemprop="image" content="https://avatars2.githubusercontent.com/u/3442641?v=3&s=460">
</span>
<span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="lxian's Blog">
<span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject">
<img style="display:none;" itemprop="url image" alt="lxian's Blog" src="">
</span>
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2015/12/06/avfoundation-video-capture1/" itemprop="url">
用Avfoundation 录像(续)
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="Post created" itemprop="dateCreated datePublished" datetime="2015-12-06T12:29:05+08:00">
2015-12-06
</time>
</span>
<span class="post-comments-count">
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-comment-o"></i>
</span>
<a href="/2015/12/06/avfoundation-video-capture1/#comments" itemprop="discussionUrl">
<span class="post-comments-count ds-thread-count" data-thread-key="2015/12/06/avfoundation-video-capture1/" itemprop="commentCount"></span>
</a>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>除了直接用AVCaptureMovieFileOutput,还可以把AVCaptureVideoDataOutput,AVCaptureAudioDataOutput 当作output。这两个class的delegate AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAudioDataOutputSampleBufferDelegate 有一个- (void)captureOutput:(AVCaptureOutput )captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection )connection 的method, 开始录像之后你可以从这个method 里面拿到每一个录下的frame,然后可以用AVAssetWriter来写入local的文件。</p>
<ol>
<li><p>加output</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">_videoDataOutput = [<span class="built_in">AVCaptureVideoDataOutput</span> new];</div><div class="line">_audioDataOutput = [<span class="built_in">AVCaptureAudioDataOutput</span> new];</div><div class="line"><span class="keyword">if</span> ([_captureSession canAddOutput:_videoDataOutput]) {</div><div class="line"> DLog(<span class="string">@"added video out"</span>);</div><div class="line"> [_captureSession addOutput:_videoDataOutput];</div><div class="line">}</div><div class="line">_videoConnection = [_videoDataOutput connectionWithMediaType:<span class="built_in">AVMediaTypeVideo</span>];</div><div class="line">_videoConnection.videoOrientation = <span class="built_in">AVCaptureVideoOrientationPortrait</span>;</div><div class="line"></div><div class="line">[_videoDataOutput setSampleBufferDelegate:<span class="keyword">self</span> queue:_videoDataOutputQueue];</div><div class="line"></div><div class="line"><span class="keyword">if</span> ([_captureSession canAddOutput:_audioDataOutput]) {</div><div class="line"> DLog(<span class="string">@"added audio out"</span>);</div><div class="line"> [_captureSession addOutput:_audioDataOutput];</div><div class="line">}</div><div class="line">_audioConnection = [_audioDataOutput connectionWithMediaType:<span class="built_in">AVMediaTypeAudio</span>];</div><div class="line">[_audioDataOutput setSampleBufferDelegate:<span class="keyword">self</span> queue:_audioDataOutputQueue];</div></pre></td></tr></table></figure>
</li>
<li><p>准备AVAssetWriter, 需要两个writerInput 分别写入video 和audio</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line">_assetWriter = [<span class="built_in">AVAssetWriter</span> assetWriterWithURL:[<span class="keyword">self</span> outputURL] fileType:<span class="built_in">AVFileTypeMPEG4</span> error:<span class="literal">nil</span>];</div><div class="line">_videoAssetWriterInput = [[<span class="built_in">AVAssetWriterInput</span> alloc] initWithMediaType:<span class="built_in">AVMediaTypeVideo</span></div><div class="line"> outputSettings:[_videoDataOutput recommendedVideoSettingsForAssetWriterWithOutputFileType:<span class="built_in">AVFileTypeMPEG4</span>]];</div><div class="line">_videoAssetWriterInput.expectsMediaDataInRealTime = <span class="literal">YES</span>;</div><div class="line">_audioAssetWriterInput = [[<span class="built_in">AVAssetWriterInput</span> alloc] initWithMediaType:<span class="built_in">AVMediaTypeAudio</span></div><div class="line"> outputSettings:[_audioDataOutput recommendedAudioSettingsForAssetWriterWithOutputFileType:<span class="built_in">AVFileTypeMPEG4</span>]];</div><div class="line">_audioAssetWriterInput.expectsMediaDataInRealTime = <span class="literal">YES</span>;</div><div class="line"></div><div class="line"><span class="keyword">if</span> ([_assetWriter canAddInput:_videoAssetWriterInput]) {</div><div class="line"> DLog(<span class="string">@"added video out writer"</span>);</div><div class="line"> [_assetWriter addInput:_videoAssetWriterInput];</div><div class="line">}</div><div class="line"><span class="keyword">if</span> ([_assetWriter canAddInput:_audioAssetWriterInput]) {</div><div class="line"> DLog(<span class="string">@"added audio out writer"</span>);</div><div class="line"> [_assetWriter addInput:_audioAssetWriterInput];</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
<li><p>填写 - (void)captureOutput:(AVCaptureOutput )captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection )connection</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div></pre></td><td class="code"><pre><div class="line">- (<span class="keyword">void</span>)captureOutput:(<span class="built_in">AVCaptureOutput</span> *)captureOutput didOutputSampleBuffer:(<span class="built_in">CMSampleBufferRef</span>)sampleBuffer fromConnection:(<span class="built_in">AVCaptureConnection</span> *)connection</div><div class="line">{</div><div class="line"> <span class="built_in">CFRetain</span>(sampleBuffer);</div><div class="line"> <span class="built_in">CMFormatDescriptionRef</span> formatDesc = <span class="built_in">CMSampleBufferGetFormatDescription</span>(sampleBuffer);</div><div class="line"> <span class="built_in">CMMediaType</span> mediaType = <span class="built_in">CMFormatDescriptionGetMediaType</span>(formatDesc);</div><div class="line"> <span class="built_in">CMTime</span> currentSampleTime = <span class="built_in">CMSampleBufferGetPresentationTimeStamp</span>(sampleBuffer);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (mediaType == kCMMediaType_Video) {</div><div class="line"> <span class="keyword">if</span>(_firstSample) {</div><div class="line"> <span class="keyword">if</span> ([_assetWriter startWriting]) {</div><div class="line"> [_assetWriter startSessionAtSourceTime:currentSampleTime];</div><div class="line"> _firstSample = <span class="literal">NO</span>;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> DLog(<span class="string">@"Error when starting avseet writer, %ld %@, %@"</span>, (<span class="keyword">long</span>)_assetWriter.status, [_assetWriter.error localizedDescription], [_assetWriter.error userInfo]);</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (_videoAssetWriterInput.readyForMoreMediaData) {</div><div class="line"> [_videoAssetWriterInput appendSampleBuffer:bufferToWrite];</div><div class="line"> }</div><div class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (mediaType == kCMMediaType_Audio && !_firstSample) {</div><div class="line"> <span class="keyword">if</span> (_audioAssetWriterInput.readyForMoreMediaData) {</div><div class="line"> [_audioAssetWriterInput appendSampleBuffer:bufferToWrite];</div><div class="line"> }</div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="built_in">CFRelease</span>(sampleBuffer);</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
<li><p>在didOutputSampleBuffer里面拿到sample buffer 之后还可以对其进行各种处理--将其转化为CIImage ,然后就可以apply 各种filter。</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">CFRetain</span>(pixelBuffer);</div><div class="line">CVPixelBufferLockBaseAddress(pixelBuffer, <span class="number">0</span> );</div><div class="line"></div><div class="line"><span class="built_in">CIImage</span> *img = [<span class="built_in">CIImage</span> imageWithCVPixelBuffer:pixelBuffer];</div><div class="line"><span class="built_in">CIFilter</span> *filter = [<span class="built_in">CIFilter</span> filterWithName:<filterName>]; <span class="comment">//具体 filter可以参考[Core Image Filter Reference](https://developer.apple.com/library/prerelease/mac/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html)</span></div><div class="line"></div><div class="line">... apply filters</div><div class="line"></div><div class="line"><span class="built_in">CIImage</span> *outputImage = [filter outputImage];</div><div class="line">[_ciContext render:outputImage toCVPixelBuffer:pixelBuffer]; <span class="comment">//把处理好的ciimage 再写回buffer</span></div><div class="line"></div><div class="line">CVPixelBufferUnlockBaseAddress(pixelBuffer, <span class="number">0</span>);</div><div class="line"><span class="built_in">CFRelease</span>(pixelBuffer);</div></pre></td></tr></table></figure>
</li>
<li><p>那么live preview 呢,其实如果没有别的要求的话可以直接用之前用的AVCaptureVideoPreviewLayer,但是如果要在live preview 里面显示filter 的效果的话。那么就要将frame 画到一个GLKView 上面,然后把这个view 展示给user.</p>
<p>create GLKView。这里要用 EAGLContext来create CIContext 这样具体draw的时候就会用GPU 来draw 了,否则将使用CPU 来画</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">_eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];</div><div class="line">_ciContext = [<span class="built_in">CIContext</span> contextWithEAGLContext:_eaglContext options:@{kCIContextWorkingColorSpace : [<span class="built_in">NSNull</span> null]} ];</div><div class="line"> </div><div class="line">GLKView *glkView = [[GLKView alloc] initWithFrame:<frame> context:_eaglContext];</div><div class="line">[glkView bindDrawable];</div><div class="line">_livePreviewView = glkView;</div></pre></td></tr></table></figure>
<p>画frame</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">CFRetain</span>(pixelBuffer);</div><div class="line">CVPixelBufferLockBaseAddress(pixelBuffer, <span class="number">0</span> );</div><div class="line"></div><div class="line"><span class="built_in">CIImage</span> *img = [<span class="built_in">CIImage</span> imageWithCVPixelBuffer:pixelBuffer];</div><div class="line"></div><div class="line">[_ciContext drawImage:outputImage inRect:previewRect fromRect:cropRect];</div><div class="line">[((GLKView *)_livePreviewView) display];</div><div class="line"></div><div class="line">CVPixelBufferUnlockBaseAddress(pixelBuffer, <span class="number">0</span>);</div><div class="line"><span class="built_in">CFRelease</span>(pixelBuffer);</div></pre></td></tr></table></figure>
</li>
<li><p>最后保存到Library</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">[_captureSession stopRunning];</div><div class="line">[_videoAssetWriterInput markAsFinished];</div><div class="line">[_audioAssetWriterInput markAsFinished];</div><div class="line"></div><div class="line">[_assetWriter finishWritingWithCompletionHandler:^{</div><div class="line"> ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];</div><div class="line"> <span class="keyword">if</span> ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:videoURL]) {</div><div class="line"> [library writeVideoAtPathToSavedPhotosAlbum:videoURL completionBlock:^(<span class="built_in">NSURL</span> *assetURL, <span class="built_in">NSError</span> *error){</div><div class="line"> <span class="keyword">if</span> (error) {</div><div class="line"> ALog(<span class="string">@"Error when saving captured video to library, error = %@, url = %@"</span>, error, assetURL);</div><div class="line"> }</div><div class="line"> }];</div><div class="line"> }</div><div class="line">}];</div></pre></td></tr></table></figure>
</li>
</ol>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<link itemprop="mainEntityOfPage" href="http://lxian2.space/2015/11/15/autolayout-content-size/">
<span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="lxian2">
<meta itemprop="description" content="">
<meta itemprop="image" content="https://avatars2.githubusercontent.com/u/3442641?v=3&s=460">
</span>
<span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="lxian's Blog">
<span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject">
<img style="display:none;" itemprop="url image" alt="lxian's Blog" src="">
</span>
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2015/11/15/autolayout-content-size/" itemprop="url">
AutoLayout Content Size
</a>
</h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="Post created" itemprop="dateCreated datePublished" datetime="2015-11-15T12:27:24+08:00">
2015-11-15
</time>
</span>
<span class="post-comments-count">
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-comment-o"></i>
</span>
<a href="/2015/11/15/autolayout-content-size/#comments" itemprop="discussionUrl">
<span class="post-comments-count ds-thread-count" data-thread-key="2015/11/15/autolayout-content-size/" itemprop="commentCount"></span>
</a>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>主要记下Intrinsic Size, Content Hugging/Compression Resistance Priority 是干什么的。</p>
<h4 id="Intrinsic-Size"><a href="#Intrinsic-Size" class="headerlink" title="Intrinsic Size"></a>Intrinsic Size</h4><p>一个view 原本应该有的size,比如一个text label 就是text label 显示完整的text 需要的size, image view 就是这个image 的size。有了Intrinsic Size 之后,再specify 了关于location 的constriant, autolayout 就可以帮你摆放这个view 了。</p>
<h4 id="Content-Compression-Resitance-Priority"><a href="#Content-Compression-Resitance-Priority" class="headerlink" title="Content Compression Resitance Priority"></a>Content Compression Resitance Priority</h4><p>一个View 反缩小的Priority。</p>
<h4 id="Content-Hugging-Priority"><a href="#Content-Hugging-Priority" class="headerlink" title="Content Hugging Priority"></a>Content Hugging Priority</h4><p>一个View 反放大的Priority。</p>
</div>
<div>
</div>
<div>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
<link itemprop="mainEntityOfPage" href="http://lxian2.space/2015/11/13/learning-cocoa-with-objc-reading-notes/">
<span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="lxian2">
<meta itemprop="description" content="">
<meta itemprop="image" content="https://avatars2.githubusercontent.com/u/3442641?v=3&s=460">
</span>
<span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="lxian's Blog">
<span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject">
<img style="display:none;" itemprop="url image" alt="lxian's Blog" src="">
</span>
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">