-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
966 lines (589 loc) · 59 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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Corotata's Blog</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="description" content="Talk is cheap, show me your work.">
<meta property="og:type" content="website">
<meta property="og:title" content="Corotata's Blog">
<meta property="og:url" content="http://corotata.github.io/index.html">
<meta property="og:site_name" content="Corotata's Blog">
<meta property="og:description" content="Talk is cheap, show me your work.">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Corotata's Blog">
<meta name="twitter:description" content="Talk is cheap, show me your work.">
<link rel="alternative" href="/atom.xml" title="Corotata's Blog" type="application/atom+xml">
<link rel="icon" href="/favicon.png">
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<div id="container">
<div class="left-col">
<div class="overlay"></div>
<div class="intrude-less">
<header id="header" class="inner">
<a href="/" class="profilepic">
<img lazy-src="http://stuweb.zjhzyg.net/2009/10/091009/images/beiji.jpg" class="js-avatar">
</a>
<hgroup>
<h1 class="header-author"><a href="/">Corotata</a></h1>
</hgroup>
<p class="header-subtitle">Talk is cheap, show me your work.</p>
<div class="switch-btn">
<div class="icon">
<div class="icon-ctn">
<div class="icon-wrap icon-house" data-idx="0">
<div class="birdhouse"></div>
<div class="birdhouse_holes"></div>
</div>
<div class="icon-wrap icon-ribbon hide" data-idx="1">
<div class="ribbon"></div>
</div>
<div class="icon-wrap icon-link hide" data-idx="2">
<div class="loopback_l"></div>
<div class="loopback_r"></div>
</div>
<div class="icon-wrap icon-me hide" data-idx="3">
<div class="user"></div>
<div class="shoulder"></div>
</div>
</div>
</div>
<div class="tips-box hide">
<div class="tips-arrow"></div>
<ul class="tips-inner">
<li>菜单</li>
<li>标签</li>
<li>友情链接</li>
<li>关于我</li>
</ul>
</div>
</div>
<div class="switch-area">
<div class="switch-wrap">
<section class="switch-part switch-part1">
<nav class="header-menu">
<ul>
<li><a href="/">主页</a></li>
<li><a href="/archives">所有文章</a></li>
</ul>
</nav>
<nav class="header-nav">
<div class="social">
<a class="github" target="_blank" href="#" title="github">github</a>
<a class="weibo" target="_blank" href="#" title="weibo">weibo</a>
<a class="rss" target="_blank" href="#" title="rss">rss</a>
<a class="zhihu" target="_blank" href="#" title="zhihu">zhihu</a>
</div>
</nav>
</section>
<section class="switch-part switch-part2">
<div class="widget tagcloud" id="js-tagcloud">
<a href="/tags/ReactiveCocoa/" style="font-size: 10px;">ReactiveCocoa</a> <a href="/tags/Swift/" style="font-size: 20px;">Swift</a> <a href="/tags/Xcode/" style="font-size: 10px;">Xcode</a> <a href="/tags/软件推荐/" style="font-size: 10px;">软件推荐</a> <a href="/tags/随笔/" style="font-size: 10px;">随笔</a>
</div>
</section>
<section class="switch-part switch-part3">
<div id="js-friends">
<a target="_blank" class="main-nav-link switch-friends-link" href="http://localhost:4000/">奥巴马的博客</a>
<a target="_blank" class="main-nav-link switch-friends-link" href="http://localhost:4000/">卡卡的美丽传说</a>
<a target="_blank" class="main-nav-link switch-friends-link" href="http://localhost:4000/">本泽马的博客</a>
<a target="_blank" class="main-nav-link switch-friends-link" href="http://localhost:4000/">吉格斯的博客</a>
<a target="_blank" class="main-nav-link switch-friends-link" href="http://localhost:4000/">习大大大不同</a>
<a target="_blank" class="main-nav-link switch-friends-link" href="http://localhost:4000/">托蒂的博客</a>
</div>
</section>
<section class="switch-part switch-part4">
<div id="js-aboutme">I'M A CHANGER,I WANT TO CHANGE MY LIFE.</div>
</section>
</div>
</div>
</header>
</div>
</div>
<div class="mid-col">
<nav id="mobile-nav">
<div class="overlay">
<div class="slider-trigger"></div>
<h1 class="header-author js-mobile-header hide">Corotata</h1>
</div>
<div class="intrude-less">
<header id="header" class="inner">
<div class="profilepic">
<img lazy-src="http://stuweb.zjhzyg.net/2009/10/091009/images/beiji.jpg" class="js-avatar">
</div>
<hgroup>
<h1 class="header-author">Corotata</h1>
</hgroup>
<p class="header-subtitle">Talk is cheap, show me your work.</p>
<nav class="header-menu">
<ul>
<li><a href="/">主页</a></li>
<li><a href="/archives">所有文章</a></li>
<div class="clearfix"></div>
</ul>
</nav>
<nav class="header-nav">
<div class="social">
<a class="github" target="_blank" href="#" title="github">github</a>
<a class="weibo" target="_blank" href="#" title="weibo">weibo</a>
<a class="rss" target="_blank" href="#" title="rss">rss</a>
<a class="zhihu" target="_blank" href="#" title="zhihu">zhihu</a>
</div>
</nav>
</header>
</div>
</nav>
<div class="body-wrap">
<article id="post-关于CTNetwokring的改造记录" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2017/04/27/关于CTNetwokring的改造记录/" class="article-date">
<time datetime="2017-04-26T16:00:00.000Z" itemprop="datePublished">2017-04-27</time>
</a>
</div>
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2017/04/27/关于CTNetwokring的改造记录/">关于CTNetwokring的改造记录</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在读这篇文章之前,大家先看一下作者Casa的<a href="https://casatwy.com/iosying-yong-jia-gou-tan-wang-luo-ceng-she-ji-fang-an.html" target="_blank" rel="external">文章</a>,以便对CTNetwokring的整体设计以及使用方式有个大体的了解。</p>
<p>其次这次改造,主要由需求驱动,因为没有以下这些问题,我也不会做这样的尝试:</p>
<ul>
<li>公司的网络库使用虽然很方便,依赖性太强,不方便测试,属于集约型的做法,导致公司不太可能写单元测试,所以没有写单元测试,又由于公司后台经常私底下改接口,导致线上版本经常出现问题。</li>
<li>CTNetworking刚出来的时候我就关注了,苦于放出来的版本,适合学习,并不合适即插即用,我一直在等有人来改造,结果两年过去了。</li>
<li>由于那是早年安居客的脱敏版,所以设计上面就或多或少有一些依赖业务的东西,建立在它们业务上,的确是最合适方便的,但也由于太合适自身业务,那么也导致无法通用化,其他公司想拿来用就必须改,对于这一点,我在这里要建议强烈批评一下Casa,开源这么好的东西出来,怎么就不弄得更方便一点呢,像CTPersistance(安利一下)那样子插上就能用多好。</li>
<li>我想要开始走向开源社区(不要脸地说,我想涨点粉),在写这个文章前,由于公司项目API一两百个,真是没有余力做短期替换,所以我所提供的那部分代码还没有真正的得到真实项目的考量,另一方面基于我自己不会写后端接口,公司内容涉密问题也导致了没法给出更多完整的使用方式,本文给出的将是我的一套YY方案,欢迎评论区拍砖。</li>
</ul>
<h2 id="改造篇"><a href="#改造篇" class="headerlink" title="改造篇"></a>改造篇</h2><p>如上面提到的,原来的CTNetworking之所以不能做到即插即用,主要有以下几点:</p>
<ol>
<li>有旧业务的依赖,比如token的拼接,url组装啊。</li>
<li>涉及面略广,作为一个网络封装层,提供了CTUDIDGenerator等UUID生成器,CTAPPContext致使引入一些不必要的业务。</li>
<li>ServiceFactory需要硬编码,他需要知道详细的业务Service,而业务的Service硬编码无疑就使得他变得不通用。</li>
</ol>
<hr>
<p>谈到要解决上面的问题,那么就有必要来讲解一下CTNetworking的基本组成设计了,这是Casa没有在他文章里面讲的东西,打个比方,比如有这么一个接口,使用CTNetworking的视角来说,它是下面这样的:</p>
<figure class="highlight oxygene"><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></pre></td><td class="code"><pre><div class="line">https:<span class="comment">//xxx.com/method?username=corotata => 完整接口</span></div><div class="line"></div><div class="line">拆解:</div><div class="line"></div><div class="line">https:<span class="comment">//xxx.com => CTNetworking中的CTService</span></div><div class="line"></div><div class="line">/<span class="function"><span class="keyword">method</span> => <span class="title">CTAPIBaseManager</span>的子类提供</span></div><div class="line"></div><div class="line"><span class="title">username</span>=<span class="title">corotata</span> => <span class="title">CTAPIBaseManager</span>的子类所对应的<span class="title">CTAPIManagerParamSource</span></div></pre></td></tr></table></figure>
<p>所以CTNetworking所做的事情,就是将上面的内容进行拆解工作,将完整的API拼接拆解开成为一个个小部件,再通过CTApiProxy、CTRequestGenerator以及CTServiceFactory做为胶水,将他们组合起来,而通过CTURLResponse做为回调输出。</p>
<hr>
<p>首先是CTService,它主要是以域名头的形式存在,很多网络库封装都会直接忽略掉这一层,相信有不少朋友也是有过以下的经验吧:</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"><span class="keyword">static</span> <span class="built_in">NSString</span> *<span class="keyword">const</span> kBaseUrl = <span class="string">@"https://abc.com"</span>;<span class="comment">//正式服</span></div><div class="line"></div><div class="line">NetworkRequestDataModel *dataModel = [[NetworkRequestDataModel alloc] init];</div><div class="line">dataModel.interfaceFlag = kLoginUrl;</div><div class="line">dataModel.url = [<span class="built_in">NSString</span> stringWithFormat:<span class="string">@"%@%@"</span>,kBaseUrl,kLoginUrl];</div><div class="line">dataModel.params = loginDic;</div><div class="line">dataModel.isRequireLogin = <span class="literal">NO</span>;</div><div class="line">dataModel.success = ^(<span class="keyword">id</span> responseObject) {</div><div class="line"> DLogInfo(<span class="string">@"登录成功"</span>); </div><div class="line">};</div><div class="line">dataModel.failure = ^(<span class="built_in">NSError</span> *error,<span class="built_in">NSInteger</span> httpStatusCode) {</div><div class="line"> DDLogInfo(<span class="string">@"登录失败"</span>); </div><div class="line">};</div><div class="line">[LGHttpManager dataTaskWithDataModel:dataModel];</div></pre></td></tr></table></figure>
<h3 id="问题1-:"><a href="#问题1-:" class="headerlink" title="问题1 :"></a>问题1 :</h3><p>基本拼接的方式,渗透到每一个调用者身上,让调用者来提供URL的拼接方式,而往往同一服务器团队,提供的API接口都会是同样的规格,以后如果接口拼接方式改动了,那无疑将会是噩梦,可能有的小伙伴会说,你不知道可以全局替换吗?可以的,无疑有点丑了点,但如果一个APP里面同时有几个服务器团队给你提供的接口呢,而且忽然说要改了拼接方式,全局改起来还是有一点难度吧,又或者是有需求加通用参数或者通用的HTTPHeader啊,那时侯我们该怎么办?程序维护,少不了就是变动。所以为了应对这样的问题,我做了Service层的改造,主要提供了以下接口,交由子类去处理:</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="comment">//CTServiceProtocol</span></div><div class="line"></div><div class="line"><span class="comment">//为某些Service需要拼凑额外字段到URL处</span></div><div class="line">- (<span class="built_in">NSDictionary</span> *)extraParmas;</div><div class="line"></div><div class="line"><span class="comment">//为某些Service需要拼凑额外的HTTPToken,如accessToken</span></div><div class="line">- (<span class="built_in">NSDictionary</span> *)extraHttpHeadParmasWithMethodName:(<span class="built_in">NSString</span> *)method;</div><div class="line"></div><div class="line"><span class="comment">//提供URL的拼接方式</span></div><div class="line">- (<span class="built_in">NSString</span> *)urlGeneratingRuleByMethodName:(<span class="built_in">NSString</span> *)method;</div><div class="line"></div><div class="line"><span class="comment">//提供拦截器集中处理Service错误问题,比如token失效要抛通知等,返回值用来做拦截特殊错误时通知上层是否还要继续回调</span></div><div class="line">- (<span class="built_in">BOOL</span>)shouldCallBackByFailedOnCallingAPI:(<span class="built_in">CTAPIBaseManager</span> *)apiManager;</div></pre></td></tr></table></figure>
<p>看源码时,就具体看下CTRequestGenerator,他主要做请求的组装加工操作,以NSURLRequest返回给CTApiProxy进行网络请求,我贴下核心的代码:<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></pre></td><td class="code"><pre><div class="line">- (<span class="built_in">NSURLRequest</span> *)generateRequestWithServiceIdentifier:(<span class="built_in">NSString</span> *)serviceIdentifier requestParams:(<span class="built_in">NSDictionary</span> *)requestParams methodName:(<span class="built_in">NSString</span> *)methodName requestWithMethod:(<span class="built_in">NSString</span> *)method {</div><div class="line"> <span class="built_in">CTService</span> *service = [[<span class="built_in">CTServiceFactory</span> sharedInstance] serviceWithIdentifier:serviceIdentifier];</div><div class="line"> <span class="built_in">NSString</span> *urlString = [service urlGeneratingRuleByMethodName:methodName];</div><div class="line"> </div><div class="line"> <span class="built_in">NSDictionary</span> *totalRequestParams = [<span class="keyword">self</span> totalRequestParamsByService:service requestParams:requestParams];</div><div class="line"> </div><div class="line"> <span class="built_in">NSMutableURLRequest</span> *request = [<span class="keyword">self</span>.httpRequestSerializer requestWithMethod:method URLString:urlString parameters:totalRequestParams error:<span class="literal">NULL</span>];</div><div class="line"> </div><div class="line"> <span class="keyword">if</span> (![method isEqualToString:<span class="string">@"GET"</span>] && [<span class="built_in">CTNetworkingConfigurationManager</span> sharedInstance].shouldSetParamsInHTTPBodyButGET) {</div><div class="line"> request.HTTPBody = [<span class="built_in">NSJSONSerialization</span> dataWithJSONObject:requestParams options:<span class="number">0</span> error:<span class="literal">NULL</span>];</div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="keyword">if</span> ([service.child respondsToSelector:<span class="keyword">@selector</span>(extraHttpHeadParmasWithMethodName:)]) {</div><div class="line"> <span class="built_in">NSDictionary</span> *dict = [service.child extraHttpHeadParmasWithMethodName:methodName];</div><div class="line"> <span class="keyword">if</span> (dict) {</div><div class="line"> [dict enumerateKeysAndObjectsUsingBlock:^(<span class="keyword">id</span> _Nonnull key, <span class="keyword">id</span> _Nonnull obj, <span class="built_in">BOOL</span> * _Nonnull stop) {</div><div class="line"> [request setValue:obj forHTTPHeaderField:key];</div><div class="line"> }];</div><div class="line"> }</div><div class="line"> }</div><div class="line"> </div><div class="line"> request.requestParams = totalRequestParams;</div><div class="line"> <span class="keyword">return</span> request;</div><div class="line">}</div><div class="line"></div><div class="line"></div><div class="line"><span class="meta">#pragma mark - private method</span></div><div class="line"><span class="comment">//根据Service拼接额外参数</span></div><div class="line">- (<span class="built_in">NSDictionary</span> *)totalRequestParamsByService:(<span class="built_in">CTService</span> *)service requestParams:(<span class="built_in">NSDictionary</span> *)requestParams {</div><div class="line"> <span class="built_in">NSMutableDictionary</span> *totalRequestParams = [<span class="built_in">NSMutableDictionary</span> dictionaryWithDictionary:requestParams];</div><div class="line"> </div><div class="line"> <span class="keyword">if</span> ([service.child respondsToSelector:<span class="keyword">@selector</span>(extraParmas)]) {</div><div class="line"> <span class="keyword">if</span> ([service.child extraParmas]) {</div><div class="line"> [[service.child extraParmas] enumerateKeysAndObjectsUsingBlock:^(<span class="keyword">id</span> _Nonnull key, <span class="keyword">id</span> _Nonnull obj, <span class="built_in">BOOL</span> * _Nonnull stop) {</div><div class="line"> [totalRequestParams setObject:obj forKey:key];</div><div class="line"> }];</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> [totalRequestParams <span class="keyword">copy</span>];</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>内容也比较简单,方法名有相关注释我也就不知道怎么解释了,至此问题1,提到的内容得到解决。</p>
<h3 id="问题2-:"><a href="#问题2-:" class="headerlink" title="问题2 :"></a>问题2 :</h3><p>关于问题2,我本来是不想写的,但由于CTNetworking的Star有快1000了,所以对于删文件这种的重大举措,就有必要提一下了,否则下次人家下了个包,就会怒喷上个版本还提供,怎么这个版本就没了,虽然是我干的,但大家@Casa吧,下面就简单聊下我删除内容的想法以及原本CTNetworking的变动内容:</p>
<ol>
<li>作为网络组件,涉及的内容应该在这个范围内,否则它应该是一个APP,而不是组件了,对于过多的功能,最简单的方式就是删,将不是必要的内容删除就可以了。</li>
<li>CTAPPContext提供太多不是CTNetworking应该提供的功能,砍掉了。</li>
<li>CTUDIDGenerator作为一个唯一ID生成器,我觉得它应该以一个通用的组件出现,原生主要是CTAPPContext在提供服务,由于CTAPPContext已经被砍掉了,所以它和框架就完全没有依赖了,所以也可以砍掉了。</li>
<li>原来的一个叫CTNetworkingConfiguration.h被砍掉了,转而增加了CTNetworkingConfigurationManager单例,提供一些默认的配置以及原生CTAPPContext提供的部分必要服务</li>
<li>将来可能还需要砍掉的如CTSignatureGenerator,CTCommonParamsGenerator,CTLocationManager等,由于有些是不是为了后期预留的暂不知道,所以就没有动了。</li>
<li>调整了大部分分类名称及方法,统一前缀CT_。</li>
</ol>
<h3 id="问题3-:"><a href="#问题3-:" class="headerlink" title="问题3 :"></a>问题3 :</h3><p>针对问题3,由于CTServiceFactory是单例,而CTServiceFactory与CTService之间的关系其实就只差一个映射字典,所以只要为它提供@{identifier1: @”GDMapService1”,identifier2: @”GDMapService2”},在这里GDMapService1即为相应的Service的字符串,CTServiceFactory使用时,则通过反映直接生成对象,这样就不用去添加不必要的引用了。</p>
<p>在这边我是让CTServiceFactory提供一个数据源,即CTServiceFactoryDataSource,其实也可以直接提供一个属性的,但不晓得当时为什么这么做的,忘记了,可能是脑抽了吧,所以使用起来,大致是这样的:</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></pre></td><td class="code"><pre><div class="line"></div><div class="line"><span class="class"><span class="keyword">@implementation</span> <span class="title">AppDelegate</span></span></div><div class="line"></div><div class="line">- (<span class="built_in">BOOL</span>)application:(<span class="built_in">UIApplication</span> *)application didFinishLaunchingWithOptions:(<span class="built_in">NSDictionary</span> *)launchOptions {</div><div class="line"> [<span class="built_in">CTServiceFactory</span> sharedInstance].dataSource = <span class="keyword">self</span>;</div><div class="line"> <span class="keyword">return</span> <span class="literal">YES</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="meta">#pragma mark - CTServiceFactoryDataSource</span></div><div class="line">- (<span class="built_in">NSDictionary</span><<span class="built_in">NSString</span> *,<span class="built_in">NSString</span> *> *)servicesKindsOfServiceFactory {</div><div class="line"> <span class="keyword">return</span> @{kCTServiceGDMapV3: <span class="string">@"GDMapService"</span>};</div><div class="line">}</div></pre></td></tr></table></figure>
<p>至此,所有改造的内容已经讲完了。</p>
<h3 id="扩展篇"><a href="#扩展篇" class="headerlink" title="扩展篇"></a>扩展篇</h3><p>现市面上,大部分APP都采用OAUTH授权登录的方式,登录完成后,会获得相应的accessToken、expireTime及refreshToken,基本上调用其他接口使用,都会在请求头里面拼接相应的accessToken,这部分上面有提到应该交由Service去处理,让Service负责拼接的工作。</p>
<p>网络请求时,token失效是会收到类型expired_access_token,而token非法时,会收到illegal_access_token,当然还有更多的情况,由于错误信息error description可能各种公司的会不一致,所以在Service层预留的shouldCallBackByFailedOnCallingAPI就是为了做这样的事情,当网络请求失败时,到service决定是否拦截并做相应处理。</p>
</div>
<div class="article-info article-info-index">
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-2017-4-6-关于组件化使用私有Pods的一些记录" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2017/04/06/2017-4-6-关于组件化使用私有Pods的一些记录/" class="article-date">
<time datetime="2017-04-06T03:49:50.000Z" itemprop="datePublished">2017-04-06</time>
</a>
</div>
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2017/04/06/2017-4-6-关于组件化使用私有Pods的一些记录/">关于组件化使用私有Pods的一些记录</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>最近在做项目的组件化,其中遇到一些问题,经常遇到自己解决过的问题又完全想不起来,于是每次都要反复查阅,很影响效率,所以打算把自己遇到的问题都记录下来,利人利己,下面我会以案例的方式,来讲述一些问题:</p>
<h3 id="案例1"><a href="#案例1" class="headerlink" title="案例1"></a>案例1</h3><blockquote>
<p>项目中图片缓存层是基于SDWebImage做的二次封装,在提交私有Pod时,出现了以下问题:</p>
<figure class="highlight"><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">-> LGWebImage (1)</div><div class="line"> - ERROR | [iOS] xcodebuild: Returned an unsuccessful exit code.</div><div class="line"> - ERROR | xcodebuild: LGWebImage/LGWebImage/LGWebImage/UIButton+LGWebCache.m:10:9: error: 'UIButton+WebCache.h' file not found with <angled> include; use "quotes" instead</div><div class="line"> - ERROR | xcodebuild: LGWebImage/LGWebImage/LGWebImage/UIImageView+LGWebCache.m:10:9: error: 'UIImageView+WebCache.h' file not found with <angled> include; use "quotes" instead</div><div class="line">></div></pre></td></tr></table></figure>
</blockquote>
<p>封装库中使用了SDWebImage中的UIImageView+WebCache和UIButton+WebCache,虽然在PodSpec文件里面添加了SDWebImage的依赖,但在打Pod时,并没有发现SDWebImage的文件头,所以代码层面就编译不过了,这时候只需要在PodSpec添加暴露SDWebImage头文件的配置即可解决问题,如下所示:</p>
<figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">s.xcconfig = { <span class="string">"HEADER_SEARCH_PATHS"</span> => <span class="string">"$(SRCROOT)/SDWebImage"</span> }</div></pre></td></tr></table></figure>
</div>
<div class="article-info article-info-index">
<p class="article-more-link">
<a href="/2017/04/06/2017-4-6-关于组件化使用私有Pods的一些记录/#more">more >></a>
</p>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-2016-06-12-Swift中小知识点手札" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2017/04/06/2016-06-12-Swift中小知识点手札/" class="article-date">
<time datetime="2017-04-06T02:04:27.000Z" itemprop="datePublished">2017-04-06</time>
</a>
</div>
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2017/04/06/2016-06-12-Swift中小知识点手札/">Swift中小知识点手札</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h3 id="Xcode快捷键"><a href="#Xcode快捷键" class="headerlink" title="Xcode快捷键"></a>Xcode快捷键</h3><table>
<thead>
<tr>
<th style="text-align:left">键位</th>
<th style="text-align:right">含义</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">Command + shift +j</td>
<td style="text-align:right">快速定位到目录</td>
</tr>
</tbody>
</table>
<h3 id="guard"><a href="#guard" class="headerlink" title="guard"></a>guard</h3><p>Swift中的常用语法,可以有效解决可选绑定形成的{}(大括号)嵌套,提高代码的可读性,语法如下:</p>
<figure class="highlight clean"><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">guard 条件表达式 else{</div><div class="line"> <span class="comment">//条件为false时,才会执行内容的内容</span></div><div class="line"> return</div><div class="line">}</div><div class="line"></div><div class="line">........</div><div class="line">........</div></pre></td></tr></table></figure>
<h3 id="try"><a href="#try" class="headerlink" title="try"></a>try</h3><p>try是Swift中的关键字,用于处理异常</p>
<table>
<thead>
<tr>
<th style="text-align:left">字段类型</th>
<th style="text-align:right">含义</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">try</td>
<td style="text-align:right">正常处理异常,需要通过添加do{} catch{}来处理</td>
</tr>
<tr>
<td style="text-align:left">try!</td>
<td style="text-align:right">告诉系统一定不会有异常,可以不添加do{} catch{},但需要注意,开发中不推荐这样写,一旦发生异常程序就会崩溃,如果没有异常,那么会返回一个确定的值</td>
</tr>
<tr>
<td style="text-align:left">try?</td>
<td style="text-align:right">告诉系统异常发生存在可能性,可以不添加do{} catch{},如果没有异常,系统会自动将结果包装成为一个可选类型,如果有异常则返回nil</td>
</tr>
</tbody>
</table>
<h3 id="public、internal、private"><a href="#public、internal、private" class="headerlink" title="public、internal、private"></a>public、internal、private</h3><table>
<thead>
<tr>
<th style="text-align:left">字段</th>
<th style="text-align:right">含义</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">public</td>
<td style="text-align:right">最大权限,可以在当前framework和其他framework中访问</td>
</tr>
<tr>
<td style="text-align:left">internal</td>
<td style="text-align:right">默认权限,可以在当前framework中任意使用</td>
</tr>
<tr>
<td style="text-align:left">private</td>
<td style="text-align:right">私有权限,只能在当前文件中访问</td>
</tr>
</tbody>
</table>
<blockquote>
<p>以上的权限可以修性属性/方法/类</p>
<p>在开发中,需要严格控制权限,特别是在Swift中,不像OC,可以将部分方法或者属性,只在.m文件中声明,来防止外部调用,Swift中则要用private来修性对应的方法或者属性</p>
</blockquote>
<h3 id="obj"><a href="#obj" class="headerlink" title="@obj"></a>@obj</h3><blockquote>
<p>Swift中所有的东西都是编译时确定的,所以Swift不像OC支持动态派发,如果想让其支持,将需要在相应方法前面添加<strong>@obj</strong>做修饰,一般会使用在给方法添加private时配套使用</p>
</blockquote>
</div>
<div class="article-info article-info-index">
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-Swift中自定义Log" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/06/12/Swift中自定义Log/" class="article-date">
<time datetime="2016-06-12T12:00:00.000Z" itemprop="datePublished">2016-06-12</time>
</a>
</div>
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/06/12/Swift中自定义Log/">Swift中自定义Log</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>用于输出的常用函数</p>
<table>
<thead>
<tr>
<th style="text-align:left">函数名</th>
<th style="text-align:right">含义</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">#function</td>
<td style="text-align:right">获取当前输出所在的文件路径</td>
</tr>
<tr>
<td style="text-align:left">#line</td>
<td style="text-align:right">获取当前输出所在的行号</td>
</tr>
<tr>
<td style="text-align:left">#file</td>
<td style="text-align:right">获取当前输出的文件名</td>
</tr>
</tbody>
</table>
<p>所以利用上面的内容,我们可以定义以下函数做为输出:</p>
<figure class="highlight swift"><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="function"><span class="keyword">func</span> <span class="title">CRLog</span><T><span class="params">(content: T, fileName:String = #file, methodName: String = #function, lineNumber: Int = #line)</span></span>{</div><div class="line"> <span class="keyword">let</span> tempFileName = (#file <span class="keyword">as</span> <span class="type">NSString</span>).pathComponents.last! <span class="keyword">as</span> <span class="type">NSString</span></div><div class="line"> tempFileName</div><div class="line"> <span class="built_in">print</span>(tempFileName.stringByDeletingPathExtension + <span class="string">"."</span> + methodName + <span class="string">"___"</span> + <span class="string">"<span class="subst">\(lineNumber)</span>"</span>)</div><div class="line">}</div></pre></td></tr></table></figure>
<p>其中后面几个值有默认值,当不输入时,则会自动获得相应内容打印.</p>
<p>如果我们有需求,当在DEBUG模式下,就打印输出,在release模式下就不打印,那么我们需要改写我们的代码如下:</p>
<figure class="highlight swift"><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="function"><span class="keyword">func</span> <span class="title">CRLog</span><T><span class="params">(content: T, fileName:String = #file, methodName: String = #function, lineNumber: Int = #line)</span></span>{</div><div class="line"> #<span class="keyword">if</span> <span class="type">DEBUG</span></div><div class="line"> <span class="keyword">let</span> tempFileName = (#file <span class="keyword">as</span> <span class="type">NSString</span>).pathComponents.last! <span class="keyword">as</span> <span class="type">NSString</span></div><div class="line"> tempFileName</div><div class="line"> <span class="built_in">print</span>(tempFileName.stringByDeletingPathExtension + <span class="string">"."</span> + methodName + <span class="string">"___"</span> + <span class="string">"<span class="subst">\(lineNumber)</span>"</span>)</div><div class="line"> #endif</div><div class="line"> </div><div class="line"> }</div></pre></td></tr></table></figure>
<p>其中DEBUG可为任意内容,由于Swift中没有像OC中自身定义了DEBUG宏,所以此处的DEBUG可以为任意值,你可以写成你的名字等等,写完后,我们需要去配置一下这个值,于是我们需要来到:<br>工程目录->Targets->Build Settings->Swift Compiler -> Custom Flags -> Other Swift Flags -> Debug,然后在里面填写 <strong>-D DEBUG </strong>,此处的DEBUG就是你上面定义的值,与代码中的那个值保持一致就可以了,至此,你可以切换成DEBUG模式和Release模式各自尝试一下输出效果。</p>
</div>
<div class="article-info article-info-index">
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-2016-06-12-QorumLogs" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/06/12/2016-06-12-QorumLogs/" class="article-date">
<time datetime="2016-06-12T07:12:38.000Z" itemprop="datePublished">2016-06-12</time>
</a>
</div>
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/06/12/2016-06-12-QorumLogs/">QorumLogs</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>##QorumLogs<br>Swift开发中,在面临Bug时,我们常常采用的方式就是暴力调试,今天我就介绍一款Swift中的Log日志,开源项目名为:QorumLogs,它能配合XcodeColors输出彩色的Log日志</p>
<p>###基本用法</p>
<figure class="highlight nix"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">QorumLogs.<span class="attr">enabled</span> = <span class="literal">true</span></div></pre></td></tr></table></figure>
<p>开启日志系统</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="selector-tag">QorumLogs</span><span class="selector-class">.test</span>()</div></pre></td></tr></table></figure>
<p>输出测试日志,这时,我们就能看到五颜色的输出日志</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">QorumLogs<span class="selector-class">.minimumLogLevelShown</span> = <span class="number">1</span></div></pre></td></tr></table></figure>
<p>设置日志输出级别,他总共有四个级别,分别为Debug,Info,Warn和Error,通过设置,我们可以通过设置输出级别来过滤掉不想输出的日志</p>
<figure class="highlight less"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="selector-tag">QorumLogs</span><span class="selector-class">.onlyShowThisFile</span>(<span class="string">"ViewController"</span>)</div></pre></td></tr></table></figure>
<p>设置只输出,ViewController这个文件的日志</p>
<figure class="highlight less"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="selector-tag">QorumLogs</span><span class="selector-class">.onlyShowTheseFiles</span>(<span class="string">"ViewController"</span>,<span class="string">"AppDelegate"</span>)</div></pre></td></tr></table></figure>
<p>设置指定多文件输出,值得注意的是,这里是大小写敏感的</p>
<figure class="highlight stylus"><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></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="title">QL1</span><span class="params">(<span class="string">"Debug"</span>)</span></span></div><div class="line"><span class="function"><span class="title">QL2</span><span class="params">(<span class="string">"Info"</span>)</span></span></div><div class="line"><span class="function"><span class="title">QL3</span><span class="params">(<span class="string">"Warn"</span>)</span></span></div><div class="line"><span class="function"><span class="title">QL4</span><span class="params">(<span class="string">"Error"</span>)</span></span></div></pre></td></tr></table></figure>
<p>QorumLogs内部定义的基本四种Tag输出</p>
</div>
<div class="article-info article-info-index">
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-2016-3-17-循环引用" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/03/17/2016-3-17-循环引用/" class="article-date">
<time datetime="2016-03-17T01:09:45.000Z" itemprop="datePublished">2016-03-17</time>
</a>
</div>
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/03/17/2016-3-17-循环引用/">循环引用</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>今天记录一下OC里面另一个常见的问题,那就是循环引用,总的来说现在我会想到的只有三种,后续如果有其他再类似的我会再一一补上:</p>
<ol>
<li>类的循环引用</li>
<li>MRC retain循环引用</li>
<li>ARC strong对象的循环引用(其实和2是一样的,只是关键字不同而已)</li>
</ol>
</div>
<div class="article-info article-info-index">
<p class="article-more-link">
<a href="/2016/03/17/2016-3-17-循环引用/#more">more >></a>
</p>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-2016-3-16-OC内存管理" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/03/16/2016-3-16-OC内存管理/" class="article-date">
<time datetime="2016-03-16T08:54:31.000Z" itemprop="datePublished">2016-03-16</time>
</a>
</div>
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/03/16/2016-3-16-OC内存管理/">OC内存管理</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>现在是求职季,OC的面试,肯定少不了内存管理,尽管现在基本都是ARC的项目,应该没有谁还在折腾MRC吧,不过这两天貌似有看到一个开源LeagueofLegends,还真是MRC,那会我看着,我只想说,哥们,你怎么如此蛋疼,没有别的意思,纯属闲扯,好吧,进入今天的话题。<br>
</div>
<div class="article-info article-info-index">
<p class="article-more-link">
<a href="/2016/03/16/2016-3-16-OC内存管理/#more">more >></a>
</p>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-2016-3-14-KVC" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/03/14/2016-3-14-KVC/" class="article-date">
<time datetime="2016-03-14T09:30:30.000Z" itemprop="datePublished">2016-03-14</time>
</a>
</div>
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/03/14/2016-3-14-KVC/">KVC</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>KVC,即是指 NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性。功能有点类似于我们平常使用的get和set方法,直接从例子来看看比较直观吧:</p>
</div>
<div class="article-info article-info-index">
<p class="article-more-link">
<a href="/2016/03/14/2016-3-14-KVC/#more">more >></a>
</p>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-2016-2-20-Swift和Objective-C中的单例" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/02/20/2016-2-20-Swift和Objective-C中的单例/" class="article-date">
<time datetime="2016-02-20T02:58:47.000Z" itemprop="datePublished">2016-02-20</time>
</a>
</div>
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/02/20/2016-2-20-Swift和Objective-C中的单例/">2016-2-20 Swift和Objective-C中的单例</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>Objective-C中单例的使用姿势:</p>
<figure class="highlight plain"><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"></div><div class="line">+(instancetype)sharedXMPPManager{</div><div class="line"> static XMPPManager *_instance;</div><div class="line"> static dispatch_once_t onceToken;</div><div class="line"> dispatch_once(&onceToken, ^{</div><div class="line"> _instance = [[self alloc] init];</div><div class="line"> });</div><div class="line"> return _instance;</div><div class="line">}</div><div class="line"></div><div class="line">+ (instancetype)allocWithZone:(struct _NSZone *)zone{</div><div class="line"> static XMPPManager *_instance;</div><div class="line"> static dispatch_once_t onceToken;</div><div class="line"> dispatch_once(&onceToken, ^{</div><div class="line"> _instance = [super allocWithZone:zone];</div><div class="line"> });</div><div class="line"> return _instance;</div><div class="line">}</div></pre></td></tr></table></figure>
<p>那么Swift中该如何写呢,首先给出一种模仿OC的写法:</p>
<figure class="highlight swift"><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">import</span> UIKit</div><div class="line"></div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">XMPPManager</span>: <span class="title">NSObject</span> </span>{</div><div class="line"> </div><div class="line"> <span class="keyword">static</span> <span class="keyword">var</span> onceToken :dispatch_once_t = <span class="number">0</span></div><div class="line"> <span class="keyword">static</span> <span class="keyword">var</span> instance :<span class="type">XMPPManager</span>?</div><div class="line"> <span class="class"><span class="keyword">class</span> <span class="title">func</span> <span class="title">sharedXMPPManager</span>()-><span class="title">XMPPManager</span> </span>{</div><div class="line"> dispatch_once(&onceToken) { () -> <span class="type">Void</span> <span class="keyword">in</span></div><div class="line"> instance = <span class="type">XMPPManager</span>()</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> instance!</div><div class="line"> }</div><div class="line"> </div><div class="line">}</div></pre></td></tr></table></figure>
<p>由于let在Swift中是线程安全的,所以又有以下这种写法,也应该是通用写法了:</p>
<figure class="highlight swift"><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="keyword">import</span> UIKit</div><div class="line"></div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">XMPPManager</span>: <span class="title">NSObject</span> </span>{</div><div class="line"> <span class="keyword">static</span> <span class="keyword">let</span> instance : <span class="type">XMPPManager</span> = <span class="type">XMPPManager</span>()</div><div class="line"> <span class="class"><span class="keyword">class</span> <span class="title">func</span> <span class="title">sharedXMPPManager</span>()-><span class="title">XMPPManager</span> </span>{</div><div class="line"> <span class="keyword">return</span> instance</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line"></div><div class="line">调用方式:<span class="type">XMPPManager</span>.sharedXMPPManager()</div></pre></td></tr></table></figure>
<p>而后,我又在Alamofire中发现另外一种写法,效果类似于上面,不过他是以属性的方式提供,</p>
<figure class="highlight swift"><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"></div><div class="line"><span class="keyword">import</span> UIKit</div><div class="line"></div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">XMPPManager</span>: <span class="title">NSObject</span> </span>{</div><div class="line"> <span class="keyword">internal</span> <span class="keyword">static</span> <span class="keyword">let</span> sharedInstance:<span class="type">XMPPManager</span> = <span class="type">XMPPManager</span>()</div><div class="line">}</div><div class="line"></div><div class="line">调用方式:<span class="type">XMPPManager</span>.sharedXMPPManager</div></pre></td></tr></table></figure>
<p>大概就这样了,暂做记录。</p>
<hr>
<p>注:版权声明:本文为博主原创文章,未经博主允许不得转载。</p>
</div>
<div class="article-info article-info-index">
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-2016-2-20在swift中使用CocoaPods" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/02/20/2016-2-20在swift中使用CocoaPods/" class="article-date">
<time datetime="2016-02-20T02:38:06.000Z" itemprop="datePublished">2016-02-20</time>
</a>
</div>
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/02/20/2016-2-20在swift中使用CocoaPods/">在swift中使用CocoaPods</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>在swift中使用CocoaPods和Objective-C中其实没啥区别,<br>在工程路径下使用,pod init 创建Profile文件<br>打开Profile文件,以下以添加SnapKit和Alamofire为例,在文件中写入</p>
<figure class="highlight elixir"><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"><span class="comment"># Uncomment this line to define a global platform for your project</span></div><div class="line"><span class="comment"># platform :ios, '8.0'</span></div><div class="line"><span class="comment"># Uncomment this line if you're using Swift</span></div><div class="line"><span class="comment"># use_frameworks!</span></div><div class="line"></div><div class="line">target <span class="string">'CRWeiBo'</span> <span class="keyword">do</span></div><div class="line">pod <span class="string">'SnapKit'</span>, <span class="string">'0.18.0'</span></div><div class="line">pod <span class="string">'Alamofire'</span>, <span class="string">'3.1.3'</span></div><div class="line"><span class="keyword">end</span></div><div class="line"></div><div class="line">target <span class="string">'CRWeiBoTests'</span> <span class="keyword">do</span></div><div class="line"></div><div class="line"><span class="keyword">end</span></div><div class="line"></div><div class="line">target <span class="string">'CRWeiBoUITests'</span> <span class="keyword">do</span></div><div class="line"></div><div class="line"><span class="keyword">end</span></div></pre></td></tr></table></figure>
<p>如profile前面提示的,如果在swift环境下添加use_frameworks!,因为我们是直接生成的Profile文件,所以直接取消上面那行注释就可以了</p>
<figure class="highlight elixir"><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"><span class="comment"># Uncomment this line to define a global platform for your project</span></div><div class="line"><span class="comment"># platform :ios, '8.0'</span></div><div class="line"><span class="comment"># Uncomment this line if you're using Swift</span></div><div class="line">use_frameworks!</div><div class="line"></div><div class="line">target <span class="string">'CRWeiBo'</span> <span class="keyword">do</span></div><div class="line">pod <span class="string">'SnapKit'</span>, <span class="string">'0.18.0'</span></div><div class="line">pod <span class="string">'Alamofire'</span>, <span class="string">'3.1.3'</span></div><div class="line"><span class="keyword">end</span></div><div class="line"></div><div class="line">target <span class="string">'CRWeiBoTests'</span> <span class="keyword">do</span></div><div class="line"></div><div class="line"><span class="keyword">end</span></div><div class="line"></div><div class="line">target <span class="string">'CRWeiBoUITests'</span> <span class="keyword">do</span></div><div class="line"></div><div class="line"><span class="keyword">end</span></div></pre></td></tr></table></figure>
<p>如果是自己手动创建的,则需要自己补上</p>
<hr>
<p>注:版权声明:本文为博主原创文章,未经博主允许不得转载。</p>
</div>
<div class="article-info article-info-index">
<div class="article-tag tagcloud">
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Swift/">Swift</a></li></ul>
</div>
<div class="clearfix"></div>
</div>
</div>
</article>
<nav id="page-nav">
<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/">Next »</a>
</nav>
</div>
<footer id="footer">
<div class="outer">
<div id="footer-info">
<div class="footer-left">
© 2017 Corotata
</div>
<div class="footer-right">
<a href="http://hexo.io/" target="_blank">Hexo</a> Theme <a href="https://github.com/litten/hexo-theme-yilia" target="_blank">Yilia</a> by Litten
</div>
</div>
</div>
</footer>
</div>
<link rel="stylesheet" href="/fancybox/jquery.fancybox.css">
<script>
var yiliaConfig = {
fancybox: true,
mathjax: true,
animate: true,
isHome: true,
isPost: false,
isArchive: false,
isTag: false,
isCategory: false,
open_in_new: false
}
</script>
<script src="http://7.url.cn/edu/jslib/comb/require-2.1.6,jquery-1.9.1.min.js"></script>
<script src="/js/main.js"></script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [ ['$','$'], ["\\(","\\)"] ],
processEscapes: true,
skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
}
});
MathJax.Hub.Queue(function() {
var all = MathJax.Hub.getAllJax(), i;
for(i=0; i < all.length; i += 1) {
all[i].SourceElement().parentNode.className += ' has-jax';
}
});
</script>
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
</div>
</body>
</html>