-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
1149 lines (719 loc) · 82.3 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 lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 7.3.0">
<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
<link rel="mask-icon" href="/images/logo.svg" color="#222">
<link rel="stylesheet" href="/css/main.css">
<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">
<script id="hexo-configurations">
var NexT = window.NexT || {};
var CONFIG = {"hostname":"appservice.club","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"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"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
</script>
<meta name="description" content="一切有为法,如梦幻泡影,如露亦如电,应作如是观。">
<meta property="og:type" content="website">
<meta property="og:title" content="梦幻泡影">
<meta property="og:url" content="http://appservice.club/index.html">
<meta property="og:site_name" content="梦幻泡影">
<meta property="og:description" content="一切有为法,如梦幻泡影,如露亦如电,应作如是观。">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="ZacharyIcoderKong">
<meta property="article:tag" content="孔德志的个人博客">
<meta name="twitter:card" content="summary">
<link rel="canonical" href="http://appservice.club/">
<script id="page-configurations">
// https://hexo.io/docs/variables.html
CONFIG.page = {
sidebar: "",
isHome : true,
isPost : false,
lang : 'zh-CN'
};
</script>
<title>梦幻泡影</title>
<noscript>
<style>
.use-motion .brand,
.use-motion .menu-item,
.sidebar-inner,
.use-motion .post-block,
.use-motion .pagination,
.use-motion .comments,
.use-motion .post-header,
.use-motion .post-body,
.use-motion .collection-header { opacity: initial; }
.use-motion .site-title,
.use-motion .site-subtitle {
opacity: initial;
top: initial;
}
.use-motion .logo-line-before i { left: initial; }
.use-motion .logo-line-after i { right: initial; }
</style>
</noscript>
</head>
<body itemscope itemtype="http://schema.org/WebPage">
<div class="container use-motion">
<div class="headband"></div>
<header class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-brand-container">
<div class="site-nav-toggle">
<div class="toggle" aria-label="切换导航栏">
<span class="toggle-line toggle-line-first"></span>
<span class="toggle-line toggle-line-middle"></span>
<span class="toggle-line toggle-line-last"></span>
</div>
</div>
<div class="site-meta">
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<h1 class="site-title">梦幻泡影</h1>
<span class="logo-line-after"><i></i></span>
</a>
<p class="site-subtitle" itemprop="description">孔思哲的博客空间</p>
</div>
<div class="site-nav-right">
<div class="toggle popup-trigger">
</div>
</div>
</div>
<nav class="site-nav">
<ul id="menu" class="main-menu menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>
</li>
</ul>
</nav>
</div>
</header>
<div class="back-to-top">
<i class="fa fa-arrow-up"></i>
<span>0%</span>
</div>
<main class="main">
<div class="main-inner">
<div class="content-wrap">
<div class="content index posts-expand">
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="http://appservice.club/2024/11/20/iOS%E5%BC%80%E5%8F%91%E6%8A%A5%E9%94%99%E7%9A%84%E9%97%AE%E9%A2%98%E4%BF%AE%E5%A4%8D%E8%AE%B0%E5%BD%95/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="ZacharyIcoderKong">
<meta itemprop="description" content="一切有为法,如梦幻泡影,如露亦如电,应作如是观。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="梦幻泡影">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2024/11/20/iOS%E5%BC%80%E5%8F%91%E6%8A%A5%E9%94%99%E7%9A%84%E9%97%AE%E9%A2%98%E4%BF%AE%E5%A4%8D%E8%AE%B0%E5%BD%95/" class="post-title-link" itemprop="url">iOS开发报错的问题修复记录</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2024-11-20 17:05:14 / 修改时间:17:37:11" itemprop="dateCreated datePublished" datetime="2024-11-20T17:05:14+08:00">2024-11-20</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>模拟器运行报错</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">post_install do |installer|</span><br><span class="line"></span><br><span class="line"> installer.pods_project.targets.each do |target|</span><br><span class="line"></span><br><span class="line"> target.build_configurations.each do |config|</span><br><span class="line"></span><br><span class="line"> \# 处理 M1 芯片上不支持 模拟器 运行问题:不仅仅编译活跃的架构,反之就是 i386、x86_64、arm64 等架构都编译。</span><br><span class="line"></span><br><span class="line"> config.build_settings['ONLY_ACTIVE_ARCH'] = 'NO'</span><br><span class="line"></span><br><span class="line"> config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = "arm64"</span><br><span class="line"></span><br><span class="line"> end</span><br><span class="line"></span><br><span class="line"> end</span><br><span class="line"></span><br><span class="line">end</span><br></pre></td></tr></table></figure>
<p>YYText YYTextAsyncLayer UIGraphicsBeginImageContext Deprecated #984</p>
<p><a href="https://github.com/ibireme/YYText/issues/984">https://github.com/ibireme/YYText/issues/984</a></p>
<h1 id="iOS-18适配问题记录-Xcode16正式版"><a href="#iOS-18适配问题记录-Xcode16正式版" class="headerlink" title="iOS 18适配问题记录(Xcode16正式版)"></a>iOS 18适配问题记录(Xcode16正式版)</h1><h3 id="问题1:ADClient编译报错问题"><a href="#问题1:ADClient编译报错问题" class="headerlink" title="问题1:ADClient编译报错问题"></a>问题1:ADClient编译报错问题</h3><h4 id="报错信息"><a href="#报错信息" class="headerlink" title="报错信息"></a>报错信息</h4><img src="/2024/11/20/iOS%E5%BC%80%E5%8F%91%E6%8A%A5%E9%94%99%E7%9A%84%E9%97%AE%E9%A2%98%E4%BF%AE%E5%A4%8D%E8%AE%B0%E5%BD%95/1177260-5902fcd45ac3365c.png" class="">
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Undefined symbols <span class="keyword">for</span> architecture arm64:</span><br><span class="line"> <span class="string">"_OBJC_CLASS_<span class="variable">$_ADClient</span>"</span>, referenced from:</span><br><span class="line"> <span class="keyword">in</span> ViewController.o</span><br><span class="line">ld: symbol(s) not found <span class="keyword">for</span> architecture arm64</span><br><span class="line">clang: error: linker <span class="built_in">command</span> failed with <span class="built_in">exit</span> code 1 (use -v to see invocation)</span><br></pre></td></tr></table></figure>
<h4 id="相关代码(demo)"><a href="#相关代码(demo)" class="headerlink" title="相关代码(demo)"></a>相关代码(demo)</h4><img src="/2024/11/20/iOS%E5%BC%80%E5%8F%91%E6%8A%A5%E9%94%99%E7%9A%84%E9%97%AE%E9%A2%98%E4%BF%AE%E5%A4%8D%E8%AE%B0%E5%BD%95/1177260-c985bd451915ac10.png" class="">
<h4 id="原因"><a href="#原因" class="headerlink" title="原因"></a>原因</h4><p>苹果对AdClicent API加了一个标识<br> ADCLIENT_DEPRECATED_IOS_90_145_OBSOLETED_180<br> 表示:iOS7.1-iOS14.5可用,iOS18彻底废弃,会在iOS18系统上编译失败。</p>
<img src="/2024/11/20/iOS%E5%BC%80%E5%8F%91%E6%8A%A5%E9%94%99%E7%9A%84%E9%97%AE%E9%A2%98%E4%BF%AE%E5%A4%8D%E8%AE%B0%E5%BD%95/1177260-6484670f130a6afd.png" class="">
<h4 id="解决办法"><a href="#解决办法" class="headerlink" title="解决办法"></a>解决办法</h4><p>使用AdService库的AAAttribution替代,注意iOS14.3才可以使用。</p>
<h4 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h4><figure class="highlight objectivec"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (@available(ios <span class="number">14.3</span>, *)) {</span><br><span class="line"> <span class="built_in">NSError</span> *error;</span><br><span class="line"> <span class="built_in">NSString</span> *token = [AAAttribution attributionTokenWithError:&error];</span><br><span class="line"> <span class="keyword">if</span> (token != <span class="literal">nil</span>) {</span><br><span class="line"> ...</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h4><p><a href="https://links.jianshu.com/go?to=https://developer.apple.com/forums/thread/759156">https://developer.apple.com/forums/thread/759156</a><br> <a href="https://links.jianshu.com/go?to=https://developer.apple.com/documentation/iad?language=objc">https://developer.apple.com/documentation/iad?language=objc</a></p>
<h3 id="问题2:Xcode16(正式版)运行时,YYCache导致crash"><a href="#问题2:Xcode16(正式版)运行时,YYCache导致crash" class="headerlink" title="问题2:Xcode16(正式版)运行时,YYCache导致crash"></a>问题2:Xcode16(正式版)运行时,YYCache导致crash</h3><h4 id="报错信息-1"><a href="#报错信息-1" class="headerlink" title="报错信息"></a>报错信息</h4><img src="/2024/11/20/iOS%E5%BC%80%E5%8F%91%E6%8A%A5%E9%94%99%E7%9A%84%E9%97%AE%E9%A2%98%E4%BF%AE%E5%A4%8D%E8%AE%B0%E5%BD%95/1177260-74e56dabcd1817a4.png" class="">
<h4 id="原因-1"><a href="#原因-1" class="headerlink" title="原因"></a>原因</h4><p>在 iOS18 中,需要提前对 sqlite3_stmt 执行 sqlite3_finalize。</p>
<h4 id="解决办法-1"><a href="#解决办法-1" class="headerlink" title="解决办法"></a>解决办法</h4><img src="/2024/11/20/iOS%E5%BC%80%E5%8F%91%E6%8A%A5%E9%94%99%E7%9A%84%E9%97%AE%E9%A2%98%E4%BF%AE%E5%A4%8D%E8%AE%B0%E5%BD%95/1177260-3b76a65dbd9d1b1f.png" class="">
<h4 id="代码-1"><a href="#代码-1" class="headerlink" title="代码"></a>代码</h4><figure class="highlight objectivec"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line">- (<span class="type">BOOL</span>)_dbClose {</span><br><span class="line"> <span class="keyword">if</span> (!_db) <span class="keyword">return</span> <span class="literal">YES</span>;</span><br><span class="line"> </span><br><span class="line"> <span class="type">int</span> result = <span class="number">0</span>;</span><br><span class="line"> <span class="type">BOOL</span> retry = <span class="literal">NO</span>;</span><br><span class="line"> <span class="type">BOOL</span> stmtFinalized = <span class="literal">NO</span>;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (@available(iOS <span class="number">18</span>, *)) {</span><br><span class="line"> <span class="keyword">if</span> (_dbStmtCache) {</span><br><span class="line"> <span class="built_in">CFIndex</span> size = <span class="built_in">CFDictionaryGetCount</span>(_dbStmtCache);</span><br><span class="line"> <span class="built_in">CFTypeRef</span> *valuesRef = (<span class="built_in">CFTypeRef</span> *)malloc(size * <span class="keyword">sizeof</span>(<span class="built_in">CFTypeRef</span>));</span><br><span class="line"> <span class="built_in">CFDictionaryGetKeysAndValues</span>(_dbStmtCache, <span class="literal">NULL</span>, (<span class="keyword">const</span> <span class="type">void</span> **)valuesRef);</span><br><span class="line"> <span class="keyword">const</span> sqlite3_stmt **stmts = (<span class="keyword">const</span> sqlite3_stmt **)valuesRef;</span><br><span class="line"> <span class="keyword">for</span> (<span class="built_in">CFIndex</span> i = <span class="number">0</span>; i < size; i ++) {</span><br><span class="line"> sqlite3_stmt *stmt = stmts[i];</span><br><span class="line"> sqlite3_finalize(stmt);</span><br><span class="line"> }</span><br><span class="line"> free(valuesRef);</span><br><span class="line"> <span class="built_in">CFRelease</span>(_dbStmtCache);</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">if</span> (_dbStmtCache) <span class="built_in">CFRelease</span>(_dbStmtCache);</span><br><span class="line"> _dbStmtCache = <span class="literal">NULL</span>;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">do</span> {</span><br><span class="line"> retry = <span class="literal">NO</span>;</span><br><span class="line"> result = sqlite3_close(_db);</span><br><span class="line"> <span class="keyword">if</span> (result == SQLITE_BUSY || result == SQLITE_LOCKED) {</span><br><span class="line"> <span class="keyword">if</span> (!stmtFinalized) {</span><br><span class="line"> stmtFinalized = <span class="literal">YES</span>;</span><br><span class="line"> sqlite3_stmt *stmt;</span><br><span class="line"> <span class="keyword">while</span> ((stmt = sqlite3_next_stmt(_db, <span class="literal">nil</span>)) != <span class="number">0</span>) {</span><br><span class="line"> sqlite3_finalize(stmt);</span><br><span class="line"> retry = <span class="literal">YES</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (result != SQLITE_OK) {</span><br><span class="line"> <span class="keyword">if</span> (_errorLogsEnabled) {</span><br><span class="line"> <span class="built_in">NSLog</span>(<span class="string">@"%s line:%d sqlite close failed (%d)."</span>, __FUNCTION__, __LINE__, result);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">while</span> (retry);</span><br><span class="line"> _db = <span class="literal">NULL</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">YES</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="参考-1"><a href="#参考-1" class="headerlink" title="参考"></a>参考</h4><p><a href="https://links.jianshu.com/go?to=https://giters.com/ibireme/YYCache/issues/166">https://giters.com/ibireme/YYCache/issues/166</a></p>
<h3 id="问题3:Xcode16正式版,addSubView-crash-(maskView)"><a href="#问题3:Xcode16正式版,addSubView-crash-(maskView)" class="headerlink" title="问题3:Xcode16正式版,addSubView crash (maskView)"></a>问题3:Xcode16正式版,addSubView crash (maskView)</h3><h4 id="报错信息-2"><a href="#报错信息-2" class="headerlink" title="报错信息"></a>报错信息</h4><img src="/2024/11/20/iOS%E5%BC%80%E5%8F%91%E6%8A%A5%E9%94%99%E7%9A%84%E9%97%AE%E9%A2%98%E4%BF%AE%E5%A4%8D%E8%AE%B0%E5%BD%95/1177260-655dd9dd0bd287c7.png" class="">
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line">*** Assertion failure in -[TestMaskView _addSubview:positioned:relativeTo:], UIView.m:<span class="number">18496</span></span><br><span class="line">*** Terminating app due to uncaught exception <span class="string">'NSInternalInconsistencyException'</span>, reason: <span class="string">'Set `maskView` (<UIView: 0x14a21ddd0; frame = (0 0; 0 0); layer = <CALayer: 0x60000314b480>>) to `nil` before adding it as a subview of <TestMaskView: 0x153e08350; frame = (0 0; 393 852); layer = <CALayer: 0x60000314b440>>'</span></span><br><span class="line">*** First <span class="keyword">throw</span> call stack:</span><br><span class="line">(</span><br><span class="line"> <span class="number">0</span> CoreFoundation <span class="number">0x00000001063540ec</span> __exceptionPreprocess + <span class="number">172</span></span><br><span class="line"> <span class="number">1</span> libobjc.A.dylib <span class="number">0x00000001048bede8</span> objc_exception_throw + <span class="number">72</span></span><br><span class="line"> <span class="number">2</span> Foundation <span class="number">0x0000000109d21aa8</span> _userInfoForFileAndLine + <span class="number">0</span></span><br><span class="line"> <span class="number">3</span> UIKitCore <span class="number">0x0000000128c0151c</span> -[<span class="title function_ invoke__">UIView</span>(Internal) _addSubview:positioned:relativeTo:] + <span class="number">1124</span></span><br><span class="line"> <span class="number">4</span> ADClientTest <span class="number">0x0000000104609660</span> -[TestMaskView initWithFrame:] + <span class="number">276</span></span><br><span class="line"> <span class="number">5</span> ADClientTest <span class="number">0x0000000104609434</span> -[ViewController viewDidLoad] + <span class="number">164</span></span><br><span class="line"> <span class="number">6</span> UIKitCore <span class="number">0x0000000127f1e69c</span> -[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] + <span class="number">80</span></span><br><span class="line"> <span class="number">7</span> UIKitCore <span class="number">0x0000000127f23238</span> -[UIViewController loadViewIfRequired] + <span class="number">908</span></span><br><span class="line"> <span class="number">8</span> UIKitCore <span class="number">0x0000000127f234e0</span> -[UIViewController view] + <span class="number">20</span></span><br><span class="line"> <span class="number">9</span> UIKitCore <span class="number">0x00000001286c3a08</span> -[UIWindow addRootViewControllerViewIfPossible] + <span class="number">132</span></span><br><span class="line"> <span class="number">10</span> UIKitCore <span class="number">0x00000001286c343c</span> -[UIWindow _updateLayerOrderingAndSetLayerHidden:actionBlock:] + <span class="number">168</span></span><br><span class="line"> <span class="number">11</span> UIKitCore <span class="number">0x00000001286c4288</span> -[UIWindow _setHidden:forced:] + <span class="number">228</span></span><br><span class="line"> <span class="number">12</span> UIKitCore <span class="number">0x00000001286d3344</span> -[UIWindow _mainQueue_makeKeyAndVisible] + <span class="number">36</span></span><br><span class="line"> <span class="number">13</span> UIKitCore <span class="number">0x000000012892dcd8</span> -[UIWindowScene _performDeferredInitialWindowUpdateForConnection] + <span class="number">204</span></span><br><span class="line"> <span class="number">14</span> UIKitCore <span class="number">0x0000000127af58f0</span> +[UIScene _sceneForFBSScene:create:withSession:connectionOptions:] + <span class="number">1164</span></span><br><span class="line"> <span class="number">15</span> UIKitCore <span class="number">0x000000012868f45c</span> -[UIApplication _connectUISceneFromFBSScene:transitionContext:] + <span class="number">808</span></span><br><span class="line"> <span class="number">16</span> UIKitCore <span class="number">0x000000012868f70c</span> -[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + <span class="number">304</span></span><br><span class="line"> <span class="number">17</span> UIKitCore <span class="number">0x000000012815ec08</span> -[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + <span class="number">260</span></span><br><span class="line"> <span class="number">18</span> FrontBoardServices <span class="number">0x0000000113090ce4</span> __95-[FBSScene _callOutQueue_didCreateWithTransitionContext:alternativeCreationCallout:completion:]_block_invoke + <span class="number">260</span></span><br><span class="line"> <span class="number">19</span> FrontBoardServices <span class="number">0x00000001130910a4</span> -[FBSScene _callOutQueue_coalesceClientSettingsUpdates:] + <span class="number">60</span></span><br><span class="line"> <span class="number">20</span> FrontBoardServices <span class="number">0x0000000113090b64</span> -[FBSScene _callOutQueue_didCreateWithTransitionContext:alternativeCreationCallout:completion:] + <span class="number">408</span></span><br><span class="line"> <span class="number">21</span> FrontBoardServices <span class="number">0x00000001130bdd50</span> __93-[FBSWorkspaceScenesClient _callOutQueue_sendDidCreateForScene:transitionContext:completion:]_block_invoke.<span class="number">156</span> + <span class="number">216</span></span><br><span class="line"> <span class="number">22</span> FrontBoardServices <span class="number">0x000000011309d618</span> -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + <span class="number">160</span></span><br><span class="line"> <span class="number">23</span> FrontBoardServices <span class="number">0x00000001130bc220</span> -[FBSWorkspaceScenesClient _callOutQueue_sendDidCreateForScene:transitionContext:completion:] + <span class="number">388</span></span><br><span class="line"> <span class="number">24</span> libdispatch.dylib <span class="number">0x000000010bdea7b8</span> _dispatch_client_callout + <span class="number">16</span></span><br><span class="line"> <span class="number">25</span> libdispatch.dylib <span class="number">0x000000010bdee3bc</span> _dispatch_block_invoke_direct + <span class="number">388</span></span><br><span class="line"> <span class="number">26</span> FrontBoardServices <span class="number">0x00000001130e0b58</span> __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + <span class="number">44</span></span><br><span class="line"> <span class="number">27</span> FrontBoardServices <span class="number">0x00000001130e0a34</span> -[FBSMainRunLoopSerialQueue _targetQueue_performNextIfPossible] + <span class="number">196</span></span><br><span class="line"> <span class="number">28</span> FrontBoardServices <span class="number">0x00000001130e0b8c</span> -[FBSMainRunLoopSerialQueue _performNextFromRunLoopSource] + <span class="number">24</span></span><br><span class="line"> <span class="number">29</span> CoreFoundation <span class="number">0x00000001062b8324</span> __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + <span class="number">24</span></span><br><span class="line"> <span class="number">30</span> CoreFoundation <span class="number">0x00000001062b826c</span> __CFRunLoopDoSource0 + <span class="number">172</span></span><br><span class="line"> <span class="number">31</span> CoreFoundation <span class="number">0x00000001062b7a2c</span> __CFRunLoopDoSources0 + <span class="number">324</span></span><br><span class="line"> <span class="number">32</span> CoreFoundation <span class="number">0x00000001062b20b0</span> __CFRunLoopRun + <span class="number">788</span></span><br><span class="line"> <span class="number">33</span> CoreFoundation <span class="number">0x00000001062b1960</span> CFRunLoopRunSpecific + <span class="number">536</span></span><br><span class="line"> <span class="number">34</span> GraphicsServices <span class="number">0x0000000117edfb10</span> GSEventRunModal + <span class="number">160</span></span><br><span class="line"> <span class="number">35</span> UIKitCore <span class="number">0x000000012868db40</span> -[UIApplication _run] + <span class="number">796</span></span><br><span class="line"> <span class="number">36</span> UIKitCore <span class="number">0x0000000128691d38</span> UIApplicationMain + <span class="number">124</span></span><br><span class="line"> <span class="number">37</span> ADClientTest <span class="number">0x0000000104609064</span> main + <span class="number">140</span></span><br><span class="line"> <span class="number">38</span> dyld <span class="number">0x00000001047cd410</span> start_sim + <span class="number">20</span></span><br><span class="line"> <span class="number">39</span> ??? <span class="number">0x000000010490a274</span> <span class="number">0x0</span> + <span class="number">4371554932</span></span><br><span class="line">)</span><br><span class="line">libc++abi: terminating due to uncaught exception of type NSException</span><br></pre></td></tr></table></figure>
<h4 id="原因-2"><a href="#原因-2" class="headerlink" title="原因"></a>原因</h4><p>iOS 18 对 UIView的maskView 增加了断言,导致如果业务代码里有同名属性可能导致触发该断言。</p>
<p>经测试发现:<br> 1.自定义UIView子视图,存在同名属性maskView,会崩溃<br> 2.自定义cell,添加到cell视图上会崩溃,添加到contentView上,则不会崩溃<br> 3.控制器里的maskView视图属性,添加到控制器view,不会崩溃</p>
<h4 id="解决办法-2"><a href="#解决办法-2" class="headerlink" title="解决办法"></a>解决办法</h4><p>修改自定义视图,将自定义子组件名为maskView的视图进行重命名。</p>
<h4 id="参考-2"><a href="#参考-2" class="headerlink" title="参考"></a>参考</h4><p><a href="https://links.jianshu.com/go?to=https://github.com/Tencent/QMUI_iOS/issues/1557">https://github.com/Tencent/QMUI_iOS/issues/1557</a></p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="http://appservice.club/2024/11/15/git%E5%B0%86%E4%B8%80%E4%B8%AA%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF%E7%9A%84%E9%83%A8%E5%88%86%E4%BF%AE%E6%94%B9%E6%8F%90%E4%BA%A4%E5%88%B0%E5%8F%A6%E4%B8%80%E4%B8%AA%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="ZacharyIcoderKong">
<meta itemprop="description" content="一切有为法,如梦幻泡影,如露亦如电,应作如是观。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="梦幻泡影">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2024/11/15/git%E5%B0%86%E4%B8%80%E4%B8%AA%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF%E7%9A%84%E9%83%A8%E5%88%86%E4%BF%AE%E6%94%B9%E6%8F%90%E4%BA%A4%E5%88%B0%E5%8F%A6%E4%B8%80%E4%B8%AA%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF/" class="post-title-link" itemprop="url">git将一个远程分支的部分修改提交到另一个远程分支</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2024-11-15 21:06:33 / 修改时间:21:08:04" itemprop="dateCreated datePublished" datetime="2024-11-15T21:06:33+08:00">2024-11-15</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h3 id="将一个远程分支的部分修改提交到另一个远程分支"><a href="#将一个远程分支的部分修改提交到另一个远程分支" class="headerlink" title="将一个远程分支的部分修改提交到另一个远程分支"></a>将一个远程分支的部分修改提交到另一个远程分支</h3><p>将一个远程分支的部分修改提交到另一个远程分支,可以使用 <code>git cherry-pick</code> 命令。这个命令可以选择特定的提交(commit)从一个分支应用到另一个分支。</p>
<ol>
<li><strong>切换到目标本地分支</strong>:<br>首先,确保您在您的本地机器上切换到了目标分支(即您想要应用修改的分支)。例如,想将修改应用到 <code>master</code> 分支,应该先切换到该分支:</li>
</ol>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git checkout master</span><br></pre></td></tr></table></figure>
<ol>
<li>确保本地分支是最新的:</li>
</ol>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git pull origin master</span><br></pre></td></tr></table></figure>
<ol>
<li><strong>找到特定的提交</strong>:<br>在另一个分支上,找出想要应用的特定提交。可以使用 <code>git log</code> 命令查看提交历史:</li>
</ol>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git log origin/feature-branch</span><br></pre></td></tr></table></figure>
<ol>
<li>找到您想要的提交,并复制它的提交哈希(commit hash)。</li>
<li><strong>使用 cherry-pick 应用修改</strong>:<br>使用 <code>git cherry-pick</code> 命令将该提交应用到当前的分支上:</li>
</ol>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git cherry-pick <commit-hash></span><br></pre></td></tr></table></figure>
<ol>
<li>如果想应用多个连续的提交,可以使用提交范围:</li>
</ol>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git cherry-pick <start-commit-hash>^..<end-commit-hash></span><br></pre></td></tr></table></figure>
<ol>
<li><strong>解决可能出现的冲突</strong>:<br>如果 <code>cherry-pick</code> 过程中出现冲突,需要解决这些冲突。完成后,继续 <code>cherry-pick</code> 过程:</li>
</ol>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git add .</span><br><span class="line">git cherry-pick --continue</span><br></pre></td></tr></table></figure>
<ol>
<li>或者,如果决定不进行 <code>cherry-pick</code>,可以取消:</li>
</ol>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git cherry-pick --abort</span><br></pre></td></tr></table></figure>
<ol>
<li><strong>推送到远程仓库</strong>:<br>一旦完成,将您的更改推送到远程仓库:</li>
</ol>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git push origin master</span><br></pre></td></tr></table></figure>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="http://appservice.club/2024/11/09/Xcode16%E6%96%B0%E5%BB%BA%E9%A1%B9%E7%9B%AEpod%E6%8A%A5%E9%94%99%E9%97%AE%E9%A2%98%E8%AE%B0%E5%BD%95/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="ZacharyIcoderKong">
<meta itemprop="description" content="一切有为法,如梦幻泡影,如露亦如电,应作如是观。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="梦幻泡影">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2024/11/09/Xcode16%E6%96%B0%E5%BB%BA%E9%A1%B9%E7%9B%AEpod%E6%8A%A5%E9%94%99%E9%97%AE%E9%A2%98%E8%AE%B0%E5%BD%95/" class="post-title-link" itemprop="url">Xcode16新建项目pod报错问题记录</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2024-11-09 10:24:46 / 修改时间:10:45:36" itemprop="dateCreated datePublished" datetime="2024-11-09T10:24:46+08:00">2024-11-09</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>Pod修改为清华源 <code>source 'https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git'</code></p>
<p>参见 <a href="https://mirrors.tuna.tsinghua.edu.cn/">清华大学开源软件镜像站</a></p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="http://appservice.club/2020/07/20/%E4%B8%BA%E4%BB%80%E4%B9%88%E8%AF%B4%E5%9F%BA%E4%BA%8ETCP%E7%9A%84%E7%A7%BB%E5%8A%A8%E7%AB%AFIM%E4%BB%8D%E7%84%B6%E9%9C%80%E8%A6%81%E5%BF%83%E8%B7%B3%E4%BF%9D%E6%B4%BB%EF%BC%9F/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="ZacharyIcoderKong">
<meta itemprop="description" content="一切有为法,如梦幻泡影,如露亦如电,应作如是观。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="梦幻泡影">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2020/07/20/%E4%B8%BA%E4%BB%80%E4%B9%88%E8%AF%B4%E5%9F%BA%E4%BA%8ETCP%E7%9A%84%E7%A7%BB%E5%8A%A8%E7%AB%AFIM%E4%BB%8D%E7%84%B6%E9%9C%80%E8%A6%81%E5%BF%83%E8%B7%B3%E4%BF%9D%E6%B4%BB%EF%BC%9F/" class="post-title-link" itemprop="url">为什么说基于TCP的移动端IM仍然需要心跳保活? </a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2020-07-20 14:10:02 / 修改时间:14:13:02" itemprop="dateCreated datePublished" datetime="2020-07-20T14:10:02+08:00">2020-07-20</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-folder"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/iOS/" itemprop="url" rel="index"><span itemprop="name">iOS</span></a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="为什么说基于TCP的移动端IM仍然需要心跳保活?"><a href="#为什么说基于TCP的移动端IM仍然需要心跳保活?" class="headerlink" title="为什么说基于TCP的移动端IM仍然需要心跳保活?"></a>为什么说基于TCP的移动端IM仍然需要心跳保活?</h1><p>(转自 <a href="http://www.52im.net/thread-281-1-1.html">http://www.52im.net/thread-281-1-1.html</a>)</p>
<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>很多人认为,TCP协议自身先天就有KeepAlive机制,为何基于它的通讯链接,仍然需要在应用层实现额外的心跳保活?本文将从移动端IM实践的角度告诉你,即使使用的是TCP协议,应用层的心跳保活仍旧必不可少。</p>
<p>在使用 TCP 长连接的 IM 服务设计中,往往都会涉及到心跳。心跳一般是指某端(绝大多数情况下是客户端)每隔一定时间向对端发送自定义指令,以判断双方是否存活,因其按照一定间隔发送,类似于心跳,故被称为心跳指令。</p>
<h3 id="TCP协议不是自带KeepAlive的吗?"><a href="#TCP协议不是自带KeepAlive的吗?" class="headerlink" title="TCP协议不是自带KeepAlive的吗?"></a>TCP协议不是自带KeepAlive的吗?</h3><p>那么问题就随之而来了:为什么需要在应用层做心跳,难道 TCP 不是个可靠连接吗?我们不能够依赖 TCP 做断线检测吗?比如使用 TCP 的 KeepAlive 机制来实现。应用层心跳是目前的最佳实践吗?怎么样的心跳才是最佳实践。</p>
<p>很多做移动端IM的同行,以前确实没有仔细考虑过这些问题,潜意识里想当然的认为这仅仅只是个简单的心跳而已啊。好吧,事实并非这么简单,请继续往下看。</p>
<h3 id="IM中保持有效长连接的重要性"><a href="#IM中保持有效长连接的重要性" class="headerlink" title="IM中保持有效长连接的重要性"></a>IM中保持有效长连接的重要性</h3><p>对于客户端而言,使用 TCP 长连接来实现业务的最大驱动力在于:在当前连接可用的情况下,每一次请求都只是简单的数据发送和接受,免去了 DNS 解析,连接建立等时间,大大加快了请求的速度,同时也有利于接受服务器的实时消息。但前提是连接可用。</p>
<p>如果连接无法很好地保持,每次请求就会变成撞大运:运气好,通过长连接发送请求并收到反馈。运气差,当前连接已失效,请求迟迟没有收到反馈直到超时,又需要一次连接建立的过程,其效率甚至还不如 HTTP。而连接保持的前提必然是检测连接的可用性,并在连接不可用时主动放弃当前连接并建立新的连接。</p>
<p>基于这个前提,必须要有一种机制用于检测连接可用性。同时移动网络的特殊性也要求客户端需要在空余时间发送一定的信令,避免连接被回收。详见微信和运营商的撕B(另一篇针对微信的信令风暴技术研究文章请见:《微信对网络影响的技术试验及分析》)。</p>
<p>而对于服务器而言,能够及时获悉连接可用性也非常重要:一方面服务器需要及时清理无效连接以减轻负载,另一方面也是业务的需求,如游戏副本中服务器需要及时处理玩家掉线带来的问题。</p>
<h3 id="TCP的KeepAlive无法替代应用层心跳保活机制的原因"><a href="#TCP的KeepAlive无法替代应用层心跳保活机制的原因" class="headerlink" title="TCP的KeepAlive无法替代应用层心跳保活机制的原因"></a>TCP的KeepAlive无法替代应用层心跳保活机制的原因</h3><p>上面说了保持连接的重要性,那么现在回到具体实现上。为什么我们需要使用应用层心跳来做检测,而不是直接使用 TCP 的特性呢?</p>
<p>我们知道 TCP 是一个基于连接的协议,其连接状态是由一个状态机进行维护,连接完毕后,双方都会处于 established 状态,这之后的状态并不会主动进行变化。这意味着如果上层不进行任何调用,一直使 TCP 连接空闲,那么这个连接虽然没有任何数据,但仍是保持连接状态,一天、一星期、甚至一个月,即使在这期间中间路由崩溃重启无数次。举个现实中经常遇到的栗子:当我们 ssh 到自己的 VPS 上,然后不小心踢掉网线,此时的网络变化并不会被 TCP 检测出,当我们重新插回网线,仍旧可以正常使用 ssh,同时此时并没有发生任何 TCP 的重连。</p>
<p>有人会说 TCP 不是有 KeepAlive 机制么,通过这个机制来实现不就可以了吗?但是事实上,TCP KeepAlive 的机制其实并不适用于此。Keep Alive 机制开启后,TCP 层将在定时时间到后发送相应的 KeepAlive 探针以确定连接可用性。一般时间为 7200 s(详情请参见《TCP/IP详解》中第23章),失败后重试 10 次,每次超时时间 75 s。显然默认值无法满足我们的需求,而修改过设置后就可以满足了吗?答案仍旧是否定的。</p>
<p>因为 TCP KeepAlive 是用于检测连接的死活,而心跳机制则附带一个额外的功能:检测通讯双方的存活状态。两者听起来似乎是一个意思,但实际上却大相径庭。</p>
<p>考虑一种情况,某台服务器因为某些原因导致负载超高,CPU 100%,无法响应任何业务请求,但是使用 TCP 探针则仍旧能够确定连接状态,这就是典型的连接活着但业务提供方已死的状态,对客户端而言,这时的最好选择就是断线后重新连接其他服务器,而不是一直认为当前服务器是可用状态,一直向当前服务器发送些必然会失败的请求。</p>
<p>从上面我们可以知道,KeepAlive 并不适用于检测双方存活的场景,这种场景还得依赖于应用层的心跳。应用层心跳有着更大的灵活性,可以控制检测时机,间隔和处理流程,甚至可以在心跳包上附带额外信息。从这个角度而言,应用层的心跳的确是最佳实践。</p>
<h3 id="心跳保活机制的实现方案参考"><a href="#心跳保活机制的实现方案参考" class="headerlink" title="心跳保活机制的实现方案参考"></a>心跳保活机制的实现方案参考</h3><p>从上面我们可以得出结论,目前而言,应用层心跳的确是检测连接有效性,双方是否存活的最佳实践,那么剩下的问题就是怎么实现。</p>
<p>最简单粗暴做法当然是定时心跳,如每隔 30 秒心跳一次,15 秒内没有收到心跳回包则认为当前连接已失效,断开连接并进行重连。这种做法最直接,实现也简单。唯一的问题是比较耗电和耗流量。以一个协议包 5 个字节计算,一天收发 2880 个心跳包,一个月就是 5 * 2 * 2880 * 30 = 0.8 M 的流量,如果手机上多装几个 IM 软件,每个月光心跳就好几兆流量没了,更不用说频繁的心跳带来的电量损耗。</p>
<p>既然频繁心跳会带来耗电和耗流量的弊端,改进的方向自然是减少心跳频率,但也不能过于影响连接检测的实时性。基于这个需求,一般可以将心跳间隔根据程序状态进行调整,当程序在后台时(这里主要考虑安卓),尽量拉长心跳间隔,5 分钟、甚至 10 分钟都可以。</p>
<p>而当 App 在前台时则按照原来规则操作。连接可靠性的判断也可以放宽,避免一次心跳超时就认为连接无效的情况,使用错误积累,只在心跳超时 n 次后才判定当前连接不可用。当然还有一些小 trick 比如从收到的最后一个指令包进行心跳包周期计时而不是固定时间,这样也能够一定程度减少心跳次数。</p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="http://appservice.club/2020/07/20/Online%E8%81%8A%E5%A4%A9%E5%8D%A1%E9%A1%BF%E5%B4%A9%E6%BA%83%E5%8E%9F%E5%9B%A0%E5%92%8C%E8%81%8A%E5%A4%A9%E6%95%B0%E6%8D%AE%E6%BA%90%E7%9A%84%E4%BC%98%E5%8C%96/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="ZacharyIcoderKong">
<meta itemprop="description" content="一切有为法,如梦幻泡影,如露亦如电,应作如是观。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="梦幻泡影">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2020/07/20/Online%E8%81%8A%E5%A4%A9%E5%8D%A1%E9%A1%BF%E5%B4%A9%E6%BA%83%E5%8E%9F%E5%9B%A0%E5%92%8C%E8%81%8A%E5%A4%A9%E6%95%B0%E6%8D%AE%E6%BA%90%E7%9A%84%E4%BC%98%E5%8C%96/" class="post-title-link" itemprop="url">Online聊天卡顿崩溃原因和聊天数据源的优化</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2020-07-20 11:08:22 / 修改时间:13:53:54" itemprop="dateCreated datePublished" datetime="2020-07-20T11:08:22+08:00">2020-07-20</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-folder"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/SAMIM/" itemprop="url" rel="index"><span itemprop="name">SAMIM</span></a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="Online聊天卡顿崩溃原因和聊天数据源的优化"><a href="#Online聊天卡顿崩溃原因和聊天数据源的优化" class="headerlink" title="Online聊天卡顿崩溃原因和聊天数据源的优化"></a>Online聊天卡顿崩溃原因和聊天数据源的优化</h1><p>测试反馈的问题有一些是界面卡顿,测试的问题不易重现和追查困难。</p>
<h3 id="怎么判断主线程是不是发生了卡顿?"><a href="#怎么判断主线程是不是发生了卡顿?" class="headerlink" title="怎么判断主线程是不是发生了卡顿?"></a>怎么判断主线程是不是发生了卡顿?</h3><p>一般来说,用户感受得到的卡顿大概有三个特征:</p>
<ol>
<li>FPS 降低</li>
<li>CPU 占用率很高</li>
<li>主线程 Runloop 执行了很久</li>
</ol>
<h3 id="我们先思考一下,界面卡顿是由哪些原因导致的?"><a href="#我们先思考一下,界面卡顿是由哪些原因导致的?" class="headerlink" title="我们先思考一下,界面卡顿是由哪些原因导致的?"></a>我们先思考一下,界面卡顿是由哪些原因导致的?</h3>
<!--noindex-->
<div class="post-button">
<a class="btn" href="/2020/07/20/Online%E8%81%8A%E5%A4%A9%E5%8D%A1%E9%A1%BF%E5%B4%A9%E6%BA%83%E5%8E%9F%E5%9B%A0%E5%92%8C%E8%81%8A%E5%A4%A9%E6%95%B0%E6%8D%AE%E6%BA%90%E7%9A%84%E4%BC%98%E5%8C%96/#more" rel="contents">
阅读全文 »
</a>
</div>
<!--/noindex-->
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="http://appservice.club/2020/07/19/Online%E4%BC%98%E5%8C%96%E8%AE%B0%E5%BD%95%E5%8F%8A%E8%BF%91%E6%9C%9F%E9%9C%80%E8%A6%81%E4%BC%98%E5%8C%96%E7%82%B9/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="ZacharyIcoderKong">
<meta itemprop="description" content="一切有为法,如梦幻泡影,如露亦如电,应作如是观。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="梦幻泡影">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2020/07/19/Online%E4%BC%98%E5%8C%96%E8%AE%B0%E5%BD%95%E5%8F%8A%E8%BF%91%E6%9C%9F%E9%9C%80%E8%A6%81%E4%BC%98%E5%8C%96%E7%82%B9/" class="post-title-link" itemprop="url">Online优化记录及近期需要优化点</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2020-07-19 19:31:50 / 修改时间:21:46:23" itemprop="dateCreated datePublished" datetime="2020-07-19T19:31:50+08:00">2020-07-19</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-folder"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/SAMIM/" itemprop="url" rel="index"><span itemprop="name">SAMIM</span></a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="Online近期优化记录及还需优化点"><a href="#Online近期优化记录及还需优化点" class="headerlink" title="Online近期优化记录及还需优化点"></a>Online近期优化记录及还需优化点</h1><h2 id="Online近期添加的新功能"><a href="#Online近期添加的新功能" class="headerlink" title="Online近期添加的新功能"></a>Online近期添加的新功能</h2><ol>
<li>会员中心的钻石会员和VIP会员功能。</li>
<li>聊天中发送iCloud文件功能。</li>
<li>类似QQ侧滑菜单和单聊和群聊中消息列表侧边栏功能。</li>
</ol>
<h2 id="Online近期优化记录"><a href="#Online近期优化记录" class="headerlink" title="Online近期优化记录"></a>Online近期优化记录</h2><ol>
<li>聊天查看大图时黑屏问题修复。</li>
<li>替换navigationBar隐藏的方法。</li>
<li>修改界面返回时偶尔卡住的问题。</li>
<li>音频通话开始后显示视频通话界面才有的翻转摄像头按钮问题修改,个人视频通话接通后自己的默认视图改为小视图,对方的视图默认是大视图。</li>
<li>杀死程序时发送的消息添加容错处理。</li>
<li>保存资料后消息列表小红点消失问题修改。</li>
<li>朋友圈发表评论删除消息等去掉文字提示和网络加载框优化体验。</li>
<li>朋友圈加入文字链接点击(网址和电话号码)功能,和长按朋友圈文字复制功能。</li>
<li>进入后台保活策略修改(改为播放无声音乐方式),进入后台断开socket改为定时器发送socket心跳,保证用户的在线状态。</li>
<li>朋友圈显示字体显示优化,刷新列表显示体验优化。</li>
<li>加载提示框加载时屏幕不可点击体验优化,网络请求超时时间统一设置为30秒。</li>
<li>Online官方公众号聊天页面的头像显示修改为默认app图标。</li>
<li>聊天中的数据源由不安全的数组改为安全数组。</li>
<li>图片发送的进度显示优化。</li>
</ol>
<h2 id="准备优化点"><a href="#准备优化点" class="headerlink" title="准备优化点"></a>准备优化点</h2><ol>
<li>用户登录过后,过段时间又重新打开app时直接进入到主界面体验优化。现在的逻辑是先走登录接口,拿到后台返回的数据后直接存储显示。这样的导致的一个体验问题是,当用户网络不好时,重新打开app会显示启动页,上面显示登录接口的加载框。直到登录接口返回数据,最多30秒的时间不能进入到app。<br>优化思路,把现在临时的个人数据存储改为文件数据存储,重新登录后先拿到存储的数据进行展示,再异步请求更新数据,用户重新打开app后无缝进入app主界面优化用户体验。</li>
</ol>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="http://appservice.club/2020/07/19/%E9%B2%81%E4%B8%9C%E5%A4%A7%E5%AD%A6%E6%AF%95%E4%B8%9A%E8%B0%83%E6%9F%A5/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="ZacharyIcoderKong">
<meta itemprop="description" content="一切有为法,如梦幻泡影,如露亦如电,应作如是观。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="梦幻泡影">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2020/07/19/%E9%B2%81%E4%B8%9C%E5%A4%A7%E5%AD%A6%E6%AF%95%E4%B8%9A%E8%B0%83%E6%9F%A5/" class="post-title-link" itemprop="url">鲁东大学毕业调查</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2020-07-19 09:57:36 / 修改时间:10:00:08" itemprop="dateCreated datePublished" datetime="2020-07-19T09:57:36+08:00">2020-07-19</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-folder"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/%E6%9D%82%E9%A1%B9/" itemprop="url" rel="index"><span itemprop="name">杂项</span></a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<img src="/2020/07/19/%E9%B2%81%E4%B8%9C%E5%A4%A7%E5%AD%A6%E6%AF%95%E4%B8%9A%E8%B0%83%E6%9F%A5/daxue1.png" class="">
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="http://appservice.club/2020/07/18/NAT-Network-Address-Translation/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="ZacharyIcoderKong">
<meta itemprop="description" content="一切有为法,如梦幻泡影,如露亦如电,应作如是观。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="梦幻泡影">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2020/07/18/NAT-Network-Address-Translation/" class="post-title-link" itemprop="url">NAT(Network Address Translation)</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2020-07-18 13:55:49 / 修改时间:14:00:21" itemprop="dateCreated datePublished" datetime="2020-07-18T13:55:49+08:00">2020-07-18</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-folder"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/" itemprop="url" rel="index"><span itemprop="name">计算机网络</span></a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="NAT(Network-Address-Translation)"><a href="#NAT(Network-Address-Translation)" class="headerlink" title="NAT(Network Address Translation)"></a>NAT(Network Address Translation)</h1><p> NAT(Network Address Translation,网络地址转换)是1994年提出的。当在专用网内部的一些主机本来已经分配到了本地IP地址(即仅在本专用网内使用的专用地址),但现在又想和因特网上的主机通信(并不需要加密)时,可使用NAT方法。<br> 这种方法需要在专用网连接到因特网的路由器上安装NAT软件。装有NAT软件的路由器叫做NAT路由器,它至少有一个有效的外部全球IP地址。这样,所有使用本地地址的主机在和外界通信时,都要在NAT路由器上将其本地地址转换成全球IP地址,才能和因特网连接。</p>
<h2 id="1-NAT功能"><a href="#1-NAT功能" class="headerlink" title="1.NAT功能"></a>1.NAT功能</h2><p> NAT不仅能解决了lP地址不足的问题,而且还能够有效地避免来自网络外部的攻击,隐藏并保护网络内部的计算机。<br> 1.宽带分享:这是 NAT 主机的最大功能。<br> 2.安全防护:NAT 之内的 PC 联机到 Internet 上面时,他所显示的 IP 是 NAT 主机的公共 IP,所以 Client 端的 PC 当然就具有一定程度的安全了,外界在进行 portscan(端口扫描) 的时候,就侦测不到源Client 端的 PC 。</p>
<h2 id="2-NAT实现方式"><a href="#2-NAT实现方式" class="headerlink" title="2. NAT实现方式"></a>2. NAT实现方式</h2><p> NAT的实现方式有三种,即静态转换Static Nat、动态转换Dynamic Nat和端口多路复用OverLoad。<br> 静态 转换是指将内部网络的私有IP地址转换为公有IP地址,IP地址对是一对一的,是一成不变的,某个私有IP地址只转换为某个公有IP地址。借助于静态转换,可以实现外部网络对内部网络中某些特定设备(如服务器)的访问。<br> 动态转换是指将内部网络的私有IP地址转换为公用IP地址时,IP地址是不确定的,是随机的,所有被授权访问上Internet的私有IP地址可随机转换为任何指定的合法IP地址。也就是说,只要指定哪些内部地址可以进行转换,以及用哪些合法地址作为外部地址时,就可以进行动态转换。动态转换可以使用多个合法外部地址集。当ISP提供的合法IP地址略少于网络内部的计算机数量时。可以采用动态转换的方式。<br> 端口多路复用( Port address Translation,PAT)是指改变外出数据包的源端口并进行端口转换,即端口地址转换(PAT,Port Address Translation).采用端口多路复用方式。内部网络的所有主机均可共享一个合法外部IP地址实现对Internet的访问,从而可以最大限度地节约IP地址资源。同时,又可隐藏网络内部的所有主机,有效避免来自internet的攻击。因此,目前网络中应用最多的就是端口多路复用方式。</p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="http://appservice.club/2020/07/07/%E5%88%9D%E8%AF%86OpenGL-ES/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="ZacharyIcoderKong">
<meta itemprop="description" content="一切有为法,如梦幻泡影,如露亦如电,应作如是观。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="梦幻泡影">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2020/07/07/%E5%88%9D%E8%AF%86OpenGL-ES/" class="post-title-link" itemprop="url">初识OpenGL ES</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2020-07-07 10:33:23 / 修改时间:10:54:19" itemprop="dateCreated datePublished" datetime="2020-07-07T10:33:23+08:00">2020-07-07</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-folder"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/OpenGL/" itemprop="url" rel="index"><span itemprop="name">OpenGL</span></a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="初识OpenGL-ES"><a href="#初识OpenGL-ES" class="headerlink" title="初识OpenGL ES"></a>初识OpenGL ES</h1><blockquote>
<p>OpenGL是用于可视化的二维和三维数据。它是一个多用途开放标准图形库,支持2D和3D数字内容创建,机械和建筑设计,虚拟原型,飞行模拟,视频游戏等应用。您可以使用OpenGL配置3D图形管道并提交数据。顶点被变换和点亮,组合成原始图像,并进行光栅化以创建2D图像。OpenGL旨在将函数调用转换为可发送到底层图形硬件的图形命令。因为这个底层硬件专门用于处理图形命令,因此OpenGL绘图通常非常快。<br>用于嵌入式系统的OpenGL(OpenGL ES)是OpenGL的简化版本,可以消除冗余功能,从而提供更容易学习和易于在移动图形硬件中实现的库。<br>OpenGL ES允许应用程序利用底层图形处理器的功能。iOS设备上的GPU可以执行复杂的2D和3D绘图,以及最终图像中每个像素的复杂阴影计算。您应该使用OpenGL ES,如果您的应用程序的设计要求要求最直接和全面的访问可能对GPU硬件</p>
</blockquote>
<p>在iOS中构建OpenGL ES应用程序需要几个注意事项,其中一些是OpenGL ES编程的通用,其中一些特定于iOS。</p>
<ul>
<li>1.确定哪个版本的OpenGL ES具有适合您应用程序的功能集,并创建一个OpenGL ES上下文。</li>
<li>2.在运行时验证设备是否支持您要使用的OpenGL ES功能。</li>
<li>3.选择在哪里渲染您的OpenGL ES内容。</li>
<li>4.确保您的应用程序在iOS中正常运行。</li>
<li>5.实现您的渲染引擎。</li>
<li>6.使用Xcode和Instruments调试您的OpenGL ES应用程序,并调整它以获得最佳性能。</li>
</ul>
<h2 id="选择哪些OpenGL-ES版本支持"><a href="#选择哪些OpenGL-ES版本支持" class="headerlink" title="选择哪些OpenGL ES版本支持"></a>选择哪些OpenGL ES版本支持</h2><p>决定您的应用程序是否应支持OpenGL ES 3.0,OpenGL ES 2.0,OpenGL ES 1.1或多个版本。<br>OpenGL ES 3.0是iOS 7中的新功能。它增加了许多新功能,可以实现更高性能,通用GPU计算技术,以及以前只能在桌面级硬件和游戏机上使用更复杂的视觉效果。<br>OpenGL ES 2.0是iOS设备的基准配置文件,具有基于可编程着色器的可配置图形流水线。<br>OpenGL ES 1.1仅提供基本的固定功能图形管道,主要用于向后兼容的iOS中。</p>
<h2 id="配置OpenGL-ES上下文"><a href="#配置OpenGL-ES上下文" class="headerlink" title="配置OpenGL ES上下文"></a>配置OpenGL ES上下文</h2><h3 id="EAGL是iOS实现的OpenGL-ES渲染上下文"><a href="#EAGL是iOS实现的OpenGL-ES渲染上下文" class="headerlink" title="EAGL是iOS实现的OpenGL ES渲染上下文"></a>EAGL是iOS实现的OpenGL ES渲染上下文</h3><p>在您的应用程序可以调用任何OpenGL ES函数之前,它必须初始化一个<br>EAGLContext对象。EAGLContext类还提供用于OpenGL ES的内容与核心动画结合的方法。</p>
<h3 id="每个上下文定位一个特定版本的OpenGL-ES"><a href="#每个上下文定位一个特定版本的OpenGL-ES" class="headerlink" title="每个上下文定位一个特定版本的OpenGL ES"></a>每个上下文定位一个特定版本的OpenGL ES</h3><p>一个EAGLContext对象只支持一个版本的OpenGL ES。例如,为OpenGL ES 1.1编写的代码与OpenGL ES 2.0或3.0上下文不兼容。使用核心OpenGL ES 2.0功能的代码与OpenGL ES 3.0上下文兼容,为OpenGL ES 2.0扩展设计的代码通常可以在OpenGL ES 3.0上下文中进行微小更改。许多新的OpenGL ES 3.0功能和增加的硬件功能需要OpenGL ES 3.0上下文。<br>您的应用程序决定时,它支持哪种OpenGL ES的版本创建和初始化的EAGLContext对象。如果设备不支持所需版本的OpenGL ES,则该initWithAPI返回nil。您的应用程序必须进行测试,以确保在使用之前成功初始化上下文。<br>为了支持OpenGL ES的多个版本作为应用程序中的渲染选项,您应该首先尝试初始化要定位的最新版本的渲染上下文。如果返回的对象是nil,则初始化旧版本的上下文。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">- (EAGLContext *)createBestEAGLContext {</span><br><span class="line"> EAGLContext * context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];</span><br><span class="line"> if(context == nil){</span><br><span class="line"> context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];</span><br><span class="line"> }</span><br><span class="line"> return context;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="绘制OpenGL-ES和GLKit"><a href="#绘制OpenGL-ES和GLKit" class="headerlink" title="绘制OpenGL ES和GLKit"></a>绘制OpenGL ES和GLKit</h2><p>GLKit框架提供视图和视图控制器类,可以消除绘图和动画化OpenGL ES内容所需的设置和维护代码。本GLKView类管理OpenGL ES的基础设施,为您的绘制代码提供一个场所,而GLKViewController类提供了在GLKit视图的OpenGL ES内容的流畅的动画渲染循环。这些类扩展了用于绘制视图内容和管理视图呈现的标准UIKit设计模式。因此,您可以将重点放在OpenGL ES渲染代码上,使您的应用程序快速启动并运行。GLKit框架还提供了其他功能来简化OpenGL ES 2.0和3.0开发。</p>
<p>使用GLKit视图渲染OpenGL ES内容</p>
<img src="/2020/07/07/%E5%88%9D%E8%AF%86OpenGL-ES/123.png" class="">
<p><a href="https://kongdezhi.com/2020/07/07/初识OpenGL-ES/OpenGL-ES-iOS-master.zip" download="OpenGL-ES-iOS-master.zip">点击下载 OpenGL+ES应用开发实践指南:iOS卷 源码</a></p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="http://appservice.club/2020/06/15/%E5%87%A1%E5%87%A1%E6%B7%BB%E5%8A%A0%E5%A5%BD%E5%8F%8B%E6%B5%81%E7%A8%8B/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="ZacharyIcoderKong">
<meta itemprop="description" content="一切有为法,如梦幻泡影,如露亦如电,应作如是观。">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="梦幻泡影">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2020/06/15/%E5%87%A1%E5%87%A1%E6%B7%BB%E5%8A%A0%E5%A5%BD%E5%8F%8B%E6%B5%81%E7%A8%8B/" class="post-title-link" itemprop="url">凡凡添加好友流程</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2020-06-15 09:43:46" itemprop="dateCreated datePublished" datetime="2020-06-15T09:43:46+08:00">2020-06-15</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar-check"></i>
</span>
<span class="post-meta-item-text">更新于</span>
<time title="修改时间:2020-06-17 19:55:51" itemprop="dateModified" datetime="2020-06-17T19:55:51+08:00">2020-06-17</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-folder"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/iOS/" itemprop="url" rel="index"><span itemprop="name">iOS</span></a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>1.进入通讯录-添加朋友界面,输入手机号搜索用户信息。<br>2.搜索到调用接口发送添加好友信息。</p>
<p>20200616<br>凡凡<br>1.消息下滑到顶部时自动拉取上一页信息显示添加。<br>2.时间戳显示添加,全局配置时间戳显示时间间隔。(删除和插入消息的时间戳显示进行中)<br>3.选择联系人界面添加。<br>4.添加创建群组接口,群管理类封装创建群接口。(后台暂未返回群ID)<br>5.添加查询用户群列表接口(后台返回结果暂时是空)</p>
<p>20200617<br>凡凡<br>1.发送消息插入时间戳显示逻辑优化。<br>2.发送消息生成消息ID的唯一标识符方法修改。<br>3.发送图片消息的构造方法修改,用消息ID+文件名构造消息一一对应的缓存文件,方便消息的缓存管理。<br>4.压缩图片获取缩略图的资源文件管理方法修改。<br>5.音频和视频消息构造和缓存处理方法修改,用消息ID+文件名构造消息一一对应的缓存文件(进行中)<br>Online<br>1.iOS13.5通知收不到处理,通知设置更新。</p>
<p>filePath = [SIMFileLocationHelper filepathForAudio:audioObject.path];</p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<nav class="pagination">
<span class="page-number current">1</span><a class="page-number" href="/page/2/">2</a><a class="page-number" href="/page/3/">3</a><a class="extend next" rel="next" href="/page/2/"><i class="fa fa-angle-right" aria-label="下一页"></i></a>
</nav>
</div>
<script>
window.addEventListener('tabs:register', () => {
let { activeClass } = CONFIG.comments;
if (CONFIG.comments.storage) {
activeClass = localStorage.getItem('comments_active') || activeClass;
}
if (activeClass) {
let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
if (activeTab) {