-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathatom.xml
More file actions
489 lines (292 loc) · 303 KB
/
atom.xml
File metadata and controls
489 lines (292 loc) · 303 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>NOTHING</title>
<icon>https://www.gravatar.com/avatar/d9ace8a0b4d76d8e8802cb1b2b061cad</icon>
<subtitle>NOTHING IS EVERYTHING.</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://charlesblog.site/"/>
<updated>2018-06-06T07:28:37.979Z</updated>
<id>http://charlesblog.site/</id>
<author>
<name>Charles</name>
<email>2275572017@qq.com</email>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>手把手教你swift项目集成cocos2dx-js模块</title>
<link href="http://charlesblog.site/2018/06/06/%E6%89%8B%E6%8A%8A%E6%89%8B%E6%95%99%E4%BD%A0swift%E9%A1%B9%E7%9B%AE%E9%9B%86%E6%88%90cocos2dx-js%E6%A8%A1%E5%9D%97/"/>
<id>http://charlesblog.site/2018/06/06/手把手教你swift项目集成cocos2dx-js模块/</id>
<published>2018-06-06T04:00:00.000Z</published>
<updated>2018-06-06T07:28:37.979Z</updated>
<content type="html"><![CDATA[<blockquote><p>本文所用各版本信息:<br>Xcode9.2 + swift4版本<br>cocos2d-x v3.17 <a href="http://www.cocos.com/?v=CN" target="_blank" rel="noopener">中文官方网站</a></p></blockquote><a id="more"></a><p>前几天在swift项目中集成了Lua模块,使得在swift工程中用Lua写游戏逻辑成为了可能,具体工程及配置见<a href="https://github.com/usiege/CocosLua" target="_blank" rel="noopener">手把手教你swift项目添加cocos2dx-lua</a>,由于公司最近要把js做的小游戏集成到iOS原生应用中,于是我们将解锁另外一个场景,好了,下面开始;</p><h2 id="同样的,首先你得有一个swift项目"><a href="#同样的,首先你得有一个swift项目" class="headerlink" title="同样的,首先你得有一个swift项目"></a>同样的,首先你得有一个swift项目</h2><p>我们从头开始,建立一个swift项目;我们默认你已经可以自己创建一个全新的swift项目了,这很简单,不是么?<br><img src="http://static.zybuluo.com/usiege/yqrdvidd7epqxjltfvrgtysf/image_1cf9dr09f7f8urifpm3pa4bg9.png" alt="swift项目结构"></p><h2 id="我们用Cocos2dx创建一个JS的项目"><a href="#我们用Cocos2dx创建一个JS的项目" class="headerlink" title="我们用Cocos2dx创建一个JS的项目"></a>我们用Cocos2dx创建一个JS的项目</h2><p>这里我们给出两种方式创建,无论哪一种,我们的集成过程都大致相同,你可以选择任何一种你认为可用的方式;</p><h3 id="CocosCreator方法集成"><a href="#CocosCreator方法集成" class="headerlink" title="CocosCreator方法集成"></a>CocosCreator方法集成</h3><p>我们最终需要的是如图下的这种目录结构,如果你已经知道这些东西是怎么弄出来的,那么,请跳过本段:<br><img src="http://static.zybuluo.com/usiege/u8yfh2zybhytwrsgqvf6e1xh/image_1cf9g35u31c6chvamcu1idd3ntm.png" alt="JS项目结构"></p><p>新建一个CocosCreator项目,在里面完成所有JS的逻辑,你也可以先设置一个空的项目,我们先把工程集成完成;<br><img src="http://static.zybuluo.com/usiege/i5z30x4o549nw7mmtahlxoa0/image_1cf9geajn1792k431mvi2kg9j313.png" alt="CocosCreator工程"></p><p>成功后我们点击项目—>构建发布:<br><img src="http://static.zybuluo.com/usiege/wwurwri3ebcrx05xifr0qjbo/image_1cf9gt11812enkm0d3c99c3qk1g.png" alt="构建发布"></p><p>发布平台选择iOS,选择一个本地发布路径;模板选择deafault,这个模式下会生成需要的cocos2dx文件夹,我们需要这个库文件夹;暂时不要勾选加密,加密的没有经过实践;</p><p><img src="http://static.zybuluo.com/usiege/rp9h61z9a4x1sc4hv9yfgkc5/image_1cf9h3npfmmhmhd9ii1v0ama41t.png" alt="构建选项,划重点"></p><p>构建好了就会生成上面的JS项目类似结构;</p><h3 id="命令行方式集成"><a href="#命令行方式集成" class="headerlink" title="命令行方式集成"></a>命令行方式集成</h3><p>这种方式类似于Lua集成方式,具体请参照<a href="https://github.com/usiege/CocosLua" target="_blank" rel="noopener">手把手教你swift项目添加cocos2dx-lua</a>中的<strong>创建一个cocos2dx-lua项目</strong>部分,只需要将命令行中的语言改为js就可以了:<br><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ ./cocos new Nothing-lua -<span class="selector-tag">p</span> com<span class="selector-class">.charles</span><span class="selector-class">.nothing</span> -l js -d /Users/dizi/Desktop</span><br></pre></td></tr></table></figure></p><h2 id="开始集成"><a href="#开始集成" class="headerlink" title="开始集成"></a>开始集成</h2><ol><li><p>拷贝cocos2dx<br>我们需要将<code>frameworks--->cocos2d-x</code>拷贝到swift目录下,注意,gitignore(自行google):<br><img src="http://static.zybuluo.com/usiege/qnh2f78lggzej9eb7szdpeab/image_1cf9hjta01op51vs51bgg1dspc0f2a.png" alt="拷贝cocos2d-x"></p></li><li><p>拷贝Classes<br>我们需要将<code>frameworks/runtime-src/Classes</code>拷贝到swift目录下:<br><img src="http://static.zybuluo.com/usiege/28hogjpi5vd1mv4zo9ure6cf/image_1cf9hr2oj1i831c80hac1e8fo12n.png" alt="拷贝Classes"></p></li><li><p>Resources<br>swift项目下建立<code>Resources</code>文件夹,将js项目资源拷贝到该目录下,如图:<br><img src="http://static.zybuluo.com/usiege/zs8ni480pwkcue4rk166s83u/image_1cf9huoo9go8e6rokaqau5c034.png" alt="拷贝资源"><br>还有一件重要的事情,这里有一个JS依赖文件夹,需要被引入,如图:<br><img src="http://static.zybuluo.com/usiege/rf8zn4sz6wixtn3wwutxb9x9/image_1cf9shqh9a82edna2otdgp79p.png" alt="JS依赖"></p></li><li><p>建立工程依赖<br>打开swift项目,引入资源:<br><img src="http://static.zybuluo.com/usiege/9y76gy2qcdo22c3dwfuzb8p7/image_1cf9ib072nr61qafeku190k25o4h.png" alt="不要问我那些蓝色文件与黄色文件的区别"><br>添加依赖工程,打开swift项目,找到我们上面拷贝的cocos2d-x,在<code>cocos2d-x/build</code>下找到<code>cocos2d_libs.xcodeproj</code>,拖到工程中;<br><img src="http://static.zybuluo.com/usiege/dyf807hcs0z74z34y60wp9cr/image_1cf9igoo21m72vai10771bts3hu4u.png" alt="cocos2d_libs.xcodeproj"><br>在<code>cocos2d-x/cocos/scripting/js-bindings/proj.ios_mac/</code>下找到<code>cocos2d_js_bindings.xcodeproj</code>拖到工程中;<br><img src="http://static.zybuluo.com/usiege/b3nb4j8migx2fl5tijy59bq5/image_1cf9ijkqiqjmjcoqhcgsiqr5r.png" alt="cocos2d_js_bindings.xcodeproj"><br>完成后如图:<br><img src="http://static.zybuluo.com/usiege/1sz3tj86m6ymblkc20v1yr1u/image_1cf9se04j17hf1nnek1lu48lne7s.png" alt="JS依赖"></p></li><li><p>配置参数<br>这项也很重要:<br><img src="http://static.zybuluo.com/usiege/pp6tlmwat1zmh5hbc0ay2uft/image_1cf9k76sq1vjq1vve165k6u11n7g7f.png" alt="Enable Bitcode"><br>在工程<code>Build Phases</code>添加依赖:<br><img src="http://static.zybuluo.com/usiege/bdqt1d7a6faf38vnkihztfrn/image_1cf9ioqa1cu4kud2l1gj1n4f6l.png" alt="添加依赖"><br>差点忘了一步,添加依赖库:<br><img src="http://static.zybuluo.com/usiege/lltp9d8slxs5bdnm29869o6b/image_1cf9k5th5vef1t4tsjvtib1f1772.png" alt="frameworks"><br>在工程<code>Build Settings--->Header search paths</code>中添加路径:<br><img src="http://static.zybuluo.com/usiege/j17pj8orqs1xcahjyds5em6n/image_1cf9sn6t8qqr6n61lma1l50luna6.png" alt="Be patient!"><br>在添加路径的过程中你需要非常的耐心,因为有可能由于cocos2dx不同的版本会出现需要不同的文件的情况,所以,请仔细查找添加到里面就可以了;</p></li><li><p>build成功,我需要一张图来庆祝一下!!!<br><img src="http://static.zybuluo.com/usiege/8aput74ae6gwq7axtqmsrjto/image_1cf9sqhc1v0k7fr1r3a1o1obs7aj.png" alt="Congratulations!"></p></li></ol><h2 id="我们来写点代码跑我们的JS"><a href="#我们来写点代码跑我们的JS" class="headerlink" title="我们来写点代码跑我们的JS"></a>我们来写点代码跑我们的JS</h2><p>首先我们需要一个桥接文件把C++的初始化操作完成;这里我们需要用OC的桥接类来完成这个任务,我自己创建了一个叫做<code>CocosBridge</code>的类,成生后我们<strong>把.m改为.mm</strong>,这个过程会自动生成一个桥接文件,如果没有自动生成,那么你需要再添加一个<code>CocosJS-Bridge-Header.h</code>的头文件,并把该文件的路径设置到<code>build settings</code>,如下:<br><img src="http://static.zybuluo.com/usiege/u0ks9mrt4znuz1me2weo0413/image_1cf9t8m9c170liqf873i228b8b0.png" alt="CocosBridge"><br><img src="http://static.zybuluo.com/usiege/f90ncmtsewljse3xyjw3cwl6/image_1cf9t9bq9r5i17qqu80s25f7gbd.png" alt="CocosJS-Bridge-Header.h"></p><p>下面我直接上代码了,具体过程自己体会,之后我们一起来研究;</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">#import <Foundation/Foundation.h></span><br><span class="line">#import "CocosViewController.h"</span><br><span class="line"></span><br><span class="line">@interface CocosBridge : NSObject</span><br><span class="line"></span><br><span class="line">+ (instancetype)shared;</span><br><span class="line"></span><br><span class="line">@property(nonatomic) CocosViewController* viewController;</span><br><span class="line"></span><br><span class="line">- (void)detoryCocos;</span><br><span class="line"></span><br><span class="line">@end</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line">#import "CocosBridge.h"</span><br><span class="line"></span><br><span class="line">#import "cocos2d.h"</span><br><span class="line">#import "AppDelegate.h"</span><br><span class="line">#import "CocosViewController.h"</span><br><span class="line"></span><br><span class="line">@interface CocosBridge()</span><br><span class="line">{</span><br><span class="line"> cocos2d::Application *_app;</span><br><span class="line">}</span><br><span class="line">@end</span><br><span class="line"></span><br><span class="line">static AppDelegate* _cocosDelegate = nil;</span><br><span class="line">@implementation CocosBridge</span><br><span class="line"></span><br><span class="line">- (instancetype)init</span><br><span class="line">{</span><br><span class="line"> self = [super init];</span><br><span class="line"> if (self) {</span><br><span class="line"> _cocosDelegate = new AppDelegate();</span><br><span class="line"> </span><br><span class="line"> //cocos2d initiatial</span><br><span class="line"> self.setupCocos;</span><br><span class="line"> }</span><br><span class="line"> return self;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">static CocosBridge* _bridge = nil;</span><br><span class="line"></span><br><span class="line">+ (instancetype)shared {</span><br><span class="line"> static dispatch_once_t onceToken;</span><br><span class="line"> dispatch_once(&onceToken, ^{</span><br><span class="line"> _bridge = [[CocosBridge alloc] init];</span><br><span class="line"> });</span><br><span class="line"> return _bridge;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">- (void)setupCocos {</span><br><span class="line"> </span><br><span class="line"> cocos2d::Application *app = cocos2d::Application::getInstance();</span><br><span class="line"> </span><br><span class="line"> // Initialize the GLView attributes</span><br><span class="line"> app->initGLContextAttrs();</span><br><span class="line"> cocos2d::GLViewImpl::convertAttrs();</span><br><span class="line"> </span><br><span class="line"> CocosViewController* cocosvc = [[CocosViewController alloc] init];</span><br><span class="line"> cocosvc.wantsFullScreenLayout = YES;</span><br><span class="line"> </span><br><span class="line"> cocos2d::GLView *glview = cocos2d::GLViewImpl::createWithEAGLView((__bridge void *)cocosvc.view);</span><br><span class="line"> cocos2d::Director::getInstance()->setOpenGLView(glview);</span><br><span class="line"> </span><br><span class="line"> app->run();</span><br><span class="line"> </span><br><span class="line"> self.viewController = cocosvc;</span><br><span class="line"> _app = app;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">- (void)detoryCocos {</span><br><span class="line"> _app->destroyInstance();</span><br><span class="line">}</span><br><span class="line">@end</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">#import <UIKit/UIKit.h></span><br><span class="line"></span><br><span class="line">@interface CocosViewController : UIViewController {</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line">- (BOOL) prefersStatusBarHidden;</span><br><span class="line"></span><br><span class="line">@end</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">#import "CocosViewController.h"</span><br><span class="line">#import "cocos2d.h"</span><br><span class="line">#import "platform/ios/CCEAGLView-ios.h"</span><br><span class="line"></span><br><span class="line">#import "CocosBridge.h"</span><br><span class="line"></span><br><span class="line">@implementation CocosViewController</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">// Implement loadView to create a view hierarchy programmatically, without using a nib.</span><br><span class="line">- (void)loadView {</span><br><span class="line"> // Initialize the CCEAGLView</span><br><span class="line"> CCEAGLView *eaglView = [CCEAGLView viewWithFrame: [UIScreen mainScreen].bounds</span><br><span class="line"> pixelFormat: (__bridge NSString *)cocos2d::GLViewImpl::_pixelFormat</span><br><span class="line"> depthFormat: cocos2d::GLViewImpl::_depthFormat</span><br><span class="line"> preserveBackbuffer: NO</span><br><span class="line"> sharegroup: nil</span><br><span class="line"> multiSampling: NO</span><br><span class="line"> numberOfSamples: 0 ];</span><br><span class="line"> </span><br><span class="line"> // Enable or disable multiple touches</span><br><span class="line"> [eaglView setMultipleTouchEnabled:NO];</span><br><span class="line"> </span><br><span class="line"> // Set EAGLView as view of RootViewController</span><br><span class="line"> self.view = eaglView;</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.</span><br><span class="line">- (void)viewDidLoad {</span><br><span class="line"> [super viewDidLoad];</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">- (void)viewWillAppear:(BOOL)animated {</span><br><span class="line"> [super viewWillAppear:animated];</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">- (void)viewDidDisappear:(BOOL)animated {</span><br><span class="line"> [super viewDidDisappear:animated];</span><br><span class="line"> CocosBridge* cb = CocosBridge.shared;</span><br><span class="line">// cb.detoryCocos;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">// For ios6, use supportedInterfaceOrientations & shouldAutorotate instead</span><br><span class="line">#ifdef __IPHONE_6_0</span><br><span class="line">- (NSUInteger) supportedInterfaceOrientations{</span><br><span class="line"> return UIInterfaceOrientationMaskAllButUpsideDown;</span><br><span class="line">}</span><br><span class="line">#endif</span><br><span class="line"></span><br><span class="line">- (BOOL) shouldAutorotate {</span><br><span class="line"> return YES;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {</span><br><span class="line"> [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];</span><br><span class="line"></span><br><span class="line"> auto glview = cocos2d::Director::getInstance()->getOpenGLView();</span><br><span class="line"></span><br><span class="line"> if (glview)</span><br><span class="line"> {</span><br><span class="line"> CCEAGLView *eaglview = (__bridge CCEAGLView *)glview->getEAGLView();</span><br><span class="line"></span><br><span class="line"> if (eaglview)</span><br><span class="line"> {</span><br><span class="line"> CGSize s = CGSizeMake([eaglview getWidth], [eaglview getHeight]);</span><br><span class="line"> cocos2d::Application::getInstance()->applicationScreenSizeChanged((int) s.width, (int) s.height);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">//fix not hide status on ios7</span><br><span class="line">- (BOOL)prefersStatusBarHidden {</span><br><span class="line"> return YES;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// Controls the application's preferred home indicator auto-hiding when this view controller is shown.</span><br><span class="line">- (BOOL)prefersHomeIndicatorAutoHidden {</span><br><span class="line"> return YES;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">- (void)didReceiveMemoryWarning {</span><br><span class="line"> // Releases the view if it doesn't have a superview.</span><br><span class="line"> [super didReceiveMemoryWarning];</span><br><span class="line"></span><br><span class="line"> // Release any cached data, images, etc that aren't in use.</span><br><span class="line">}</span><br><span class="line">@end</span><br></pre></td></tr></table></figure><p>然后我们在<code>ViewController</code>里添加一个按钮,推出我们的JS页面,上图吧:</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@IBAction</span> <span class="function"><span class="keyword">func</span> <span class="title">testAction</span><span class="params">(<span class="number">_</span> sender: Any)</span></span> {</span><br><span class="line"> <span class="keyword">let</span> cocosbridge = <span class="type">CocosBridge</span>.shared()</span><br><span class="line"> <span class="keyword">let</span> cocosvc = cocosbridge?.viewController</span><br><span class="line"> navigationController?.pushViewController(cocosvc!, animated: <span class="literal">true</span>)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="http://static.zybuluo.com/usiege/w0wl0yqcq34qx246h7zfk2p9/image_1cf9v50dlcfn13h1n2c1e2d1ggucq.png" alt="完成!!!"></p>]]></content>
<summary type="html">
<blockquote>
<p>本文所用各版本信息:<br>Xcode9.2 + swift4版本<br>cocos2d-x v3.17 <a href="http://www.cocos.com/?v=CN" target="_blank" rel="noopener">中文官方网站</a></p>
</blockquote>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="swift" scheme="http://charlesblog.site/tags/swift/"/>
<category term="js" scheme="http://charlesblog.site/tags/js/"/>
<category term="cocos2dx" scheme="http://charlesblog.site/tags/cocos2dx/"/>
</entry>
<entry>
<title>Cocos2dx-js与swift项目的互相调用</title>
<link href="http://charlesblog.site/2018/06/06/Cocos2dx-js%E4%B8%8Eswift%E9%A1%B9%E7%9B%AE%E7%9A%84%E4%BA%92%E7%9B%B8%E8%B0%83%E7%94%A8/"/>
<id>http://charlesblog.site/2018/06/06/Cocos2dx-js与swift项目的互相调用/</id>
<published>2018-06-06T00:46:00.000Z</published>
<updated>2018-06-06T11:32:04.761Z</updated>
<content type="html"><![CDATA[<p>本篇是上一篇配置swift-cocos2dx-js的后续,如有不清楚请查看上篇<a href="https://github.com/usiege/CocosJS" target="_blank" rel="noopener">手把手教你swift项目集成cocos2dx-js模块</a>,具体代码也在此处;</p><a id="more"></a><h2 id="用CocosCreator创建一个场景"><a href="#用CocosCreator创建一个场景" class="headerlink" title="用CocosCreator创建一个场景"></a>用CocosCreator创建一个场景</h2><p>打开CocosCreator新建一个项目<br><img src="http://static.zybuluo.com/usiege/eip7mgw056j3ywf0qpgmcu8m/image_1cfabu1tj9sd14fp82d5pvfvk9.png" alt="新建js项目"></p><p>在项目中如图双击scene,点击精灵<br><img src="http://static.zybuluo.com/usiege/ogbb2ren37w7am2h32p53tsn/image_1cfac14uf1ljp121lfu71tnq1kr4m.png" alt="准备添加一个事件"></p><p>在script上右击新建一个脚本,将脚本拖到右边的属性选择器里;<br><img src="http://static.zybuluo.com/usiege/z0pie8qzxiyvi7j3rr9bxrtm/image_1cfachupv1fk61srv1lb91sk81psj13.png" alt="新建一个脚本"></p><p>双击打开脚本,我们在里面写点东西,这里是重点,敲黑板啦!!!<br><figure class="highlight js"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// onLoad () {},</span></span><br><span class="line"></span><br><span class="line"> start () {</span><br><span class="line"> <span class="keyword">this</span>.node.on(<span class="string">'touchend'</span>,()=> {</span><br><span class="line"> </span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'start btn load , this is also a test!'</span>);</span><br><span class="line"> <span class="keyword">var</span> ret = jsb.reflection.callStaticMethod(<span class="string">"NativeOcClass"</span>, <span class="string">"callNativeUIWithTitle:andContent:"</span>, <span class="string">"cocos2d-js"</span>, <span class="string">"Yes! you call a Native UI from Reflection"</span>);</span><br><span class="line"> <span class="built_in">console</span>.log(ret);</span><br><span class="line"> })</span><br><span class="line"> },</span><br><span class="line"><span class="comment">//解释一下上面的代码</span></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">我们实际上用到的只是一个方法,即callStaticMethod;</span></span><br><span class="line"><span class="comment">该方法的参数:</span></span><br><span class="line"><span class="comment">第一个:一个OC类名;</span></span><br><span class="line"><span class="comment">第二个:该OC对象的方法名;</span></span><br><span class="line"><span class="comment">第三个:就按这个写就可以了;</span></span><br><span class="line"><span class="comment">第四个:js要给oc传的参数;</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure></p><p>这样是不是不够直观,我们把项目构建好到swift工程里看一下;</p><p>点击CocosCreator菜单栏项目,构建发布,如图设置:<br><img src="http://static.zybuluo.com/usiege/wgrpbk4kdvdhtx45e8l1j99a/image_1cfad49r0n0qtmtca115up381g.png" alt="构建发布"></p><p>在项目目录下找到如图文件:<br><img src="http://static.zybuluo.com/usiege/s657c8vpfggbrodfhujvj8bi/image_1cfad5eji2b7e3ttib1b1h1ig61t.png" alt="这些资源要拷贝"></p><h2 id="我们转到swift项目中去"><a href="#我们转到swift项目中去" class="headerlink" title="我们转到swift项目中去"></a>我们转到swift项目中去</h2><p>拷贝到Resources中:<br><img src="http://static.zybuluo.com/usiege/6wve325sa8dc6kz243yc8uwh/image_1cfad7vodl4c1oicoio140h1rm92a.png" alt="Resources"></p><p>打开之前的swift项目,将Resources中的文件引入到工程里:<br><img src="http://static.zybuluo.com/usiege/yxm1pf6vfk6renm786n0j5cg/image_1cfada9chggo3p11nmagb3puk2n.png" alt="引入到swift工程"></p><p>打开<code>project.js</code>,可以看到我们之前写的事件:<br><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">testbutton: [<span class="function"><span class="keyword">function</span>(<span class="params">t, e, o</span>) </span>{</span><br><span class="line"><span class="meta">"use strict"</span>;</span><br><span class="line">cc._RF.push(e, <span class="string">"b6a52AhNWVJ6oIZk3VBVDFd"</span>, <span class="string">"testbutton"</span>);</span><br><span class="line">cc.Class({</span><br><span class="line">extends: cc.Component,</span><br><span class="line">properties: {},</span><br><span class="line">start: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"><span class="keyword">this</span>.node.on(<span class="string">"touchend"</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">"js --------> oc"</span>);</span><br><span class="line"><span class="keyword">var</span> t = jsb.reflection.callStaticMethod(<span class="string">"NativeOcClass"</span>, <span class="string">"callNativeUIWithTitle:andContent:"</span>, <span class="string">"cocos2d-js"</span>, <span class="string">"Yes! you call a Native UI from Reflection"</span>);</span><br><span class="line"><span class="built_in">console</span>.log(t);</span><br><span class="line">});</span><br><span class="line">}</span><br><span class="line">});</span><br><span class="line">cc._RF.pop();</span><br><span class="line">}, {}]</span><br></pre></td></tr></table></figure></p><p>接下来我们写一个接收类:<br><img src="http://static.zybuluo.com/usiege/2tdwxye3zjb2njjcscizoan6/image_1cfaddqp818un1a3fb9j13205it34.png" alt="NativeOcClass"></p><figure class="highlight plain"><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">#import <Foundation/Foundation.h></span><br><span class="line"></span><br><span class="line">@interface NativeOcClass : NSObject</span><br><span class="line"></span><br><span class="line">+(NSString *)callNativeUIWithTitle:(NSString *) title andContent:(NSString *)content;</span><br><span class="line"></span><br><span class="line">@end</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">#import "NativeOcClass.h"</span><br><span class="line">#import <UIKit/UIKit.h></span><br><span class="line">@implementation NativeOcClass</span><br><span class="line"></span><br><span class="line">+(NSString *)callNativeUIWithTitle:(NSString *) title andContent:(NSString *)content{</span><br><span class="line"> printf("oc file called \n!");</span><br><span class="line"> UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title message:content delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];</span><br><span class="line"> [alertView show];</span><br><span class="line"> return @"oc --------> js";</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">@end</span><br></pre></td></tr></table></figure><p>我们弹出一个原生的Alert,并将结果返回给js;<br>看控制台打印:</p><p><img src="http://static.zybuluo.com/usiege/o84cqc480keeaoj89vsuwqh0/image_1cfadk65g1si71n351mjq1frrqr23h.png" alt="打印出来喽!"></p><p>好了,这篇算是一个补充,余下的就自己搞吧!!!<br>其实该项目的套路是通过c++跟js进行绑定,跟调用lua脚本的方法如出一辙,具体可参见网上的例子,单独写一个调用的例子,就很好理解了,本篇就到这里了,谢谢!!!</p>]]></content>
<summary type="html">
<p>本篇是上一篇配置swift-cocos2dx-js的后续,如有不清楚请查看上篇<a href="https://github.com/usiege/CocosJS" target="_blank" rel="noopener">手把手教你swift项目集成cocos2dx-js模块</a>,具体代码也在此处;</p>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="swift" scheme="http://charlesblog.site/tags/swift/"/>
<category term="js" scheme="http://charlesblog.site/tags/js/"/>
<category term="cocos2dx" scheme="http://charlesblog.site/tags/cocos2dx/"/>
</entry>
<entry>
<title>手把手教你swift项目添加cocos2dx-lua</title>
<link href="http://charlesblog.site/2018/06/03/%E6%89%8B%E6%8A%8A%E6%89%8B%E6%95%99%E4%BD%A0swift%E9%A1%B9%E7%9B%AE%E6%B7%BB%E5%8A%A0cocos2dx-lua/"/>
<id>http://charlesblog.site/2018/06/03/手把手教你swift项目添加cocos2dx-lua/</id>
<published>2018-06-03T00:46:00.000Z</published>
<updated>2018-06-06T07:28:41.365Z</updated>
<content type="html"><![CDATA[<blockquote><p>本文所用各版本信息:<br>Xcode9.2 + swift4版本<br>cocos2d-x v3.17 <a href="http://www.cocos.com/?v=CN" target="_blank" rel="noopener">中文官方网站</a></p></blockquote><a id="more"></a><h2 id="集成思路"><a href="#集成思路" class="headerlink" title="集成思路"></a>集成思路</h2><p>首先网上给出一个C系的思路,本人未亲测,并且以C调用lua,绕过了cocos2d-x的调用思路,不觉得这种方式很好,所以弃之;</p><p><img src="http://static.zybuluo.com/usiege/uevib9k48ouoh5tzfcdsuco2/image_1cf0chaibo2h1okm1gb01n031lna9.png" alt="C语言调用思路"></p><p>本文思路如图:<br><img src="http://static.zybuluo.com/usiege/pbbigdacwd8wt5dfgj5n1dh1/image_1cf0ck09i8q81o3a1edd16k01n42m.png" alt="swift->objective-c->c++->lua"><br>首先swift与objective-c的互相调用非常方便,其次oc只需要将.m文件写成.mm就可以在实现中直接调用c++方法,并且c++可以直接绑定lua,这样一来,就实现了,ios系语言写主框架,lua写游戏逻辑,直接通过<code>ViewController</code>展现就可以了;并且lua脚本可以像资源添加的方式直接在文件夹中替换,非常方便;基于以上思路,说干就干;</p><h2 id="首先你需要一个swift项目"><a href="#首先你需要一个swift项目" class="headerlink" title="首先你需要一个swift项目"></a>首先你需要一个swift项目</h2><p>新建一个swift语言写的工程,我们默认你已经会用Xcode做这件事了,于是,工程的结构先大致看一下;</p><p><img src="http://static.zybuluo.com/usiege/gaqy8723btnkzhb00sy41cuo/image_1cf2g3usa1ojcb531vik14mcq0d13.png" alt="Nothing项目结构"></p><p><img src="http://static.zybuluo.com/usiege/8ne4u18l390hg8tyb6rirgrh/image_1cf2g61423hj8ks12ngn544ov1g.png" alt="image_1cf2g61423hj8ks12ngn544ov1g.png-122.4kB"></p><p>这里是我自己的swift工程,上面的是总结构,下面的是内部工程结构,我们这里只关注一下<strong>bridge</strong>,首先创建一个<code>CocosViewController</code>的控制器,这里的控制器可以是OC类型的,也可以使用swift类型的(由于我们需要用OC做桥接文件,所以需要我们创建一个OC的类,我这里自己写了一个单例用来做桥接,所以控制器就无所谓是OC还是swift了),用来呈现我们用cocos2dx-lua展现的游戏页面;在swift工程中添加OC文件会自动生成桥接文件,名字如图;另外还需要注意一点,<code>CocosViewController</code>的.m文件要修改成.mm类型,这样就可以在实现中直接调用C++的类了;</p><p>创建好后先不要动,我们再来创建一个OC类型的单例,用来进行引擎的初始化操作,以及对lua游戏操作进行封装,我自己命名为<code>LuaBridge</code>;<br><img src="http://static.zybuluo.com/usiege/5d9md3gqr7g6mbctjg5xkyj9/image_1cf2h2kvq7381eho18ieh5v1s5o1t.png" alt="image_1cf2h2kvq7381eho18ieh5v1s5o1t.png-12kB"></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">#import "LuaBridge.h"</span><br><span class="line">#include "CocosLua.hpp"</span><br><span class="line"></span><br><span class="line">@interface LuaBridge()</span><br><span class="line">{</span><br><span class="line"> CocosLua _cocosLua;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">@end</span><br><span class="line"></span><br><span class="line">@implementation LuaBridge</span><br><span class="line"></span><br><span class="line">- (instancetype)init</span><br><span class="line">{</span><br><span class="line"> self = [super init];</span><br><span class="line"> if (self) {</span><br><span class="line"> _cocosLua = CocosLua();</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"> return self;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">static LuaBridge* _bridge = nil;</span><br><span class="line"></span><br><span class="line">+ (instancetype)shared {</span><br><span class="line"> static dispatch_once_t onceToken;</span><br><span class="line"> dispatch_once(&onceToken, ^{</span><br><span class="line"> _bridge = [[LuaBridge alloc] init];</span><br><span class="line"> });</span><br><span class="line"> return _bridge;</span><br><span class="line">}</span><br><span class="line">@end</span><br></pre></td></tr></table></figure><p>上面出现的<code>CocosLua</code>是一个c++的类,在工程中自己创建的;创建它的目的是用来封装cocos2dx-lua的操作,这个类直接被隐藏在<code>LuaBridge</code>单例中,在实际应用过程中可能用的不是很多,我们这里出现它只是为了说明本文的类型结构;</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">ifndef</span> CocosLua_hpp</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> CocosLua_hpp</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CocosLua</span> {</span></span><br><span class="line"> </span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> CocosLua();</span><br><span class="line"> ~CocosLua();</span><br><span class="line"> </span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">cocos_lua</span><span class="params">()</span></span>;</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">/* CocosLua_hpp */</span></span></span><br></pre></td></tr></table></figure><h2 id="创建一个cocos2dx-lua项目"><a href="#创建一个cocos2dx-lua项目" class="headerlink" title="创建一个cocos2dx-lua项目"></a>创建一个cocos2dx-lua项目</h2><p>首先我们需要去cocos官网上下载cocos2dx源码,链接在本文开始,我自己下载的是v3.17版本,下载的是zip包,解压后如下图:</p><p><img src="http://static.zybuluo.com/usiege/jcs6xlchdkv5153hmba0mczo/image_1cf2mkgfu1m1uk0i13ppv7jieh3h.png" alt="image_1cf2mkgfu1m1uk0i13ppv7jieh3h.png-77.4kB"></p><p>接下来打开终端,我们创建一个lua项目;</p><p><img src="http://static.zybuluo.com/usiege/6re1nikuq5yi42grr3llcyp2/image_1cf2mm4hr2387mi1snp1iv51gtb3u.png" alt="image_1cf2mm4hr2387mi1snp1iv51gtb3u.png-82.5kB"></p><p>一路cd到我们下载的cocos2dx文件夹下,然后:<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> <span class="built_in">cd</span> tools/cocos2d-console/bin/</span></span><br></pre></td></tr></table></figure></p><p>到上面的这个目录下新建工程,使用下面的命令格式:<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">cocos new <span class="tag"><<span class="name">game</span> <span class="attr">name</span>></span> -p <span class="tag"><<span class="name">package</span> <span class="attr">identifier</span>></span> -l <span class="tag"><<span class="name">language</span>></span> -d <span class="tag"><<span class="name">location</span>></span></span><br><span class="line"><span class="tag"><<span class="name">game</span> <span class="attr">name</span>></span> 工程名</span><br><span class="line"><span class="tag"><<span class="name">package</span> <span class="attr">identifier</span>></span> 包名,bundle id</span><br><span class="line"><span class="tag"><<span class="name">language</span>></span> 所用语言 cpp lua js</span><br><span class="line"><span class="tag"><<span class="name">location</span>></span> 项目创建路径</span><br></pre></td></tr></table></figure></p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ ./cocos new Nothing-lua -<span class="selector-tag">p</span> com<span class="selector-class">.charles</span><span class="selector-class">.nothing</span> -l lua -d /Users/dizi/Desktop</span><br></pre></td></tr></table></figure><p><img src="http://static.zybuluo.com/usiege/g32j6k9a6u3k8n8u8bdon702/image_1cf2n16id1lfp13phripbgh13ta4b.png" alt="image_1cf2n16id1lfp13phripbgh13ta4b.png-153.7kB"></p><p><img src="http://static.zybuluo.com/usiege/ekm9ac1ee3lvxobwy2nw0e50/image_1cf2n2esh15vo18se12q01i7dih54o.png" alt="image_1cf2n2esh15vo18se12q01i7dih54o.png-29kB"></p><h2 id="整合swift项目与lua项目"><a href="#整合swift项目与lua项目" class="headerlink" title="整合swift项目与lua项目"></a>整合swift项目与lua项目</h2><p>如果你做到这一步,那么我们离成功不远了;接下来我们要把lua项目里的资源拷贝到swift项目中,具体跟着我一步一步做;</p><ol><li><p>把lua项目下<code>frameworks/cocos2d-x</code>文件夹拖动到swift目录下:<br><img src="http://static.zybuluo.com/usiege/slid6pe7k8nhx6nqcgik1lan/image_1cf2ni2nnkpq1pmrsbd1iippri55.png" alt="image_1cf2ni2nnkpq1pmrsbd1iippri55.png-160.2kB"><br>这里说一点,如果工程是用git管理,因为cocos2d-x下文件比较多,而且是cocos2dx代码文件,所以不必要上传,可添加.gitignore文件:<br><img src="http://static.zybuluo.com/usiege/a2dz2qu36yco9mctyogm3p2x/image_1cf2o45re1ahs1lvjn8mca14be5i.png" alt="image_1cf2o45re1ahs1lvjn8mca14be5i.png-16.3kB"></p></li><li><p>把lua项目下<code>frameworks/runtime-src/Classes</code>文件夹拖动到swift目录下:<br><img src="http://static.zybuluo.com/usiege/3jj0oybm87eqo5gyf1t4s8nl/image_1cf2o6cm9rhe1tj416tl1acf8285v.png" alt="image_1cf2o6cm9rhe1tj416tl1acf8285v.png-197.8kB"></p></li><li><p>在swift项目目录下新建<code>Resources</code>文件夹,将lua项目中的如图三项拷贝进该文件夹下,这样以后lua的所有资源则将全部在该目录下替换,不需要修改工程中其他地方:<br><img src="http://static.zybuluo.com/usiege/0jirzqr476njjw7mnn9pa0wc/image_1cf2obieh1vrtujma7ucml86d6c.png" alt="image_1cf2obieh1vrtujma7ucml86d6c.png-112.3kB"></p></li><li><p>将刚刚添加的文件引用到工程项目中:<br><img src="http://static.zybuluo.com/usiege/ibrq5jlvye4djt47bz2x8p5b/image_1cf2ogs2gai2rj01e701jks1q2h79.png" alt="image_1cf2ogs2gai2rj01e701jks1q2h79.png-75.4kB"><br><img src="http://static.zybuluo.com/usiege/wm1ea7a5s5kj4sgmci64atfh/image_1cf2pbtk51lrv1kek18me1i5brlh8j.png" alt="image_1cf2pbtk51lrv1kek18me1i5brlh8j.png-68.5kB"><br>注意我们的coco2d-x目录并不需要一并引入到工程中,我们不会用到它(不引用它并不说不会用到,不要删掉,不要删掉,不要删掉!!!);<br>PS:这里注意蓝色文件夹和黄色文件夹的区别;</p></li></ol><h2 id="工程环境配置"><a href="#工程环境配置" class="headerlink" title="工程环境配置"></a>工程环境配置</h2><p>接下来到了重头戏,工程环境配置,这个部分我们需要耐心一点,因为有很多路径需要我们自己去找,还要搞清楚几个不同的工程项目配置,我们一步一步来;</p><ol><li><p>引入工程文件,这几个工程文件分别生成cocos-lib以及调拭用.a库,以下依次:<br><img src="http://static.zybuluo.com/usiege/pzv7pmmzyqhfgxprukdom5g2/image_1cf2vge2nmebc02hcgk8k1a199g.png" alt="image_1cf2vge2nmebc02hcgk8k1a199g.png-241.5kB"><br><img src="http://static.zybuluo.com/usiege/grjzsjx2vtnbhq1814kzd1m2/image_1cf2vjknh14co12bq15jqahuh0a9t.png" alt="image_1cf2vjknh14co12bq15jqahuh0a9t.png-103.2kB"><br><img src="http://static.zybuluo.com/usiege/6ph26ry963spcimacjhgmrnc/image_1cf2vl0kf1skll42p86qi11k16aa.png" alt="image_1cf2vl0kf1skll42p86qi11k16aa.png-156.1kB"></p></li><li><p>接下来配置资源库,点击工程TARGETS->Build Phases,在Target Dependencies中添加:<br><img src="http://static.zybuluo.com/usiege/f24ifjqb73s2qw6kk92ddnmo/image_1cf2vs1jffgj8avof61vg11iuaan.png" alt="image_1cf2vs1jffgj8avof61vg11iuaan.png-85.6kB"><br>在Link Binary With Libraries中添加如下支持库,其中lib文件需要打开Add other添加,按shift + command + G,在其中输入<code>/usr/lib</code>;<br><img src="http://static.zybuluo.com/usiege/v9m64x38qh0k224c0wgot4v2/image_1cf304l9cja61nu71r9h1l8b539b4.png" alt="image_1cf304l9cja61nu71r9h1l8b539b4.png-118.7kB"><br><img src="http://static.zybuluo.com/usiege/yvan9ltqx99nggchr66yvkz0/image_1cf309lts1b921oan4rhvkd1svebh.png" alt="image_1cf309lts1b921oan4rhvkd1svebh.png-110.7kB"></p></li><li><p>cocos2dx不支持bitcode,在buildsetting中<code>Enable Bitcode</code>改为NO;<br><img src="http://static.zybuluo.com/usiege/fzjz3bofezeaed0u9adg16lf/image_1cf30d889rs6173d8s411e0i5jbu.png" alt="image_1cf30d889rs6173d8s411e0i5jbu.png-21.7kB"><br>C++编译器部分:<br><img src="http://static.zybuluo.com/usiege/48wj5plpail9zyyz1p4nf23g/image_1cf30ekpb1omd1rj61m56qo1eracb.png" alt="image_1cf30ekpb1omd1rj61m56qo1eracb.png-26.4kB"></p></li><li><p><code>Header Search Paths</code>中添加:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash">(inherited)</span></span><br><span class="line"><span class="meta">$</span><span class="bash">(PROJECT_DIR)/cocos2d-x/cocos</span></span><br><span class="line"><span class="meta">$</span><span class="bash">(PROJECT_DIR)/cocos2d-x/external/lua/tolua</span></span><br><span class="line"><span class="meta">$</span><span class="bash">(PROJECT_DIR)/cocos2d-x/external/lua/lua</span></span><br><span class="line"><span class="meta">$</span><span class="bash">(PROJECT_DIR)/cocos2d-x/external/lua</span></span><br><span class="line"><span class="meta">$</span><span class="bash">(PROJECT_DIR)/cocos2d-x/external</span></span><br><span class="line"><span class="meta">$</span><span class="bash">(PROJECT_DIR)/cocos2d-x/Classes</span></span><br></pre></td></tr></table></figure></li></ol><p><img src="http://static.zybuluo.com/usiege/lzykomwd0fpqyrypl5atgg39/image_1cf30m5opf41hq513ib1eekflbco.png" alt="image_1cf30m5opf41hq513ib1eekflbco.png-130.9kB"></p><ol start="5"><li>引入工程配置:<br><code>cocos2d_libs.xcodeproj</code>工程配置中,确保以下架构都支持;<br><img src="http://static.zybuluo.com/usiege/bkt68q28zl1nn42kbivw3xzv/image_1cf30qh2sddp1mi95kj89o1725d5.png" alt="image_1cf30qh2sddp1mi95kj89o1725d5.png-52.8kB"><br><code>cocos2d_lua_bindings.xcodeproj</code>工程配置中,确保以下支持平台为iOS;<br><img src="http://static.zybuluo.com/usiege/3d0dh82hc2f1izglc03j0e19/image_1cf30sk2o1211j4t88f11lt172dff.png" alt="image_1cf30sk2o1211j4t88f11lt172dff.png-98.9kB"></li><li>好了,开始编译你的工程吧!</li></ol><h2 id="去倒杯水吧,这个过程会很久。。。"><a href="#去倒杯水吧,这个过程会很久。。。" class="headerlink" title="去倒杯水吧,这个过程会很久。。。"></a>去倒杯水吧,这个过程会很久。。。</h2><p><img src="http://static.zybuluo.com/usiege/lrxbyw47jmdpd4tnr8sg9i5t/image_1cf31g68atfq3l31v3uf4n1nm6fs.png" alt="image_1cf31g68atfq3l31v3uf4n1nm6fs.png-8.4kB"><br>Congratulations! 至此,工程已经全部配置完毕,你已经解决一个大Boss了;<br>今天就到这里吧,之后我们再续如何用swift调用lua <a href="http://" target="_blank" rel="noopener">手把手教你swift项目添加cocos2dx-lua(2)</a></p>]]></content>
<summary type="html">
<blockquote>
<p>本文所用各版本信息:<br>Xcode9.2 + swift4版本<br>cocos2d-x v3.17 <a href="http://www.cocos.com/?v=CN" target="_blank" rel="noopener">中文官方网站</a></p>
</blockquote>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="swift" scheme="http://charlesblog.site/tags/swift/"/>
<category term="cocos2dx" scheme="http://charlesblog.site/tags/cocos2dx/"/>
<category term="lua" scheme="http://charlesblog.site/tags/lua/"/>
</entry>
<entry>
<title>用TextKit搞点事情</title>
<link href="http://charlesblog.site/2018/05/23/%E7%94%A8TextKit%E6%90%9E%E7%82%B9%E4%BA%8B%E6%83%85/"/>
<id>http://charlesblog.site/2018/05/23/用TextKit搞点事情/</id>
<published>2018-05-23T02:00:00.000Z</published>
<updated>2018-05-23T02:46:22.637Z</updated>
<content type="html"><![CDATA[<p>搞事情,就是要搞事情!</p><a id="more"></a><p>[toc]</p><h2 id="先搞清楚族谱"><a href="#先搞清楚族谱" class="headerlink" title="先搞清楚族谱"></a>先搞清楚族谱</h2><blockquote><p><img src="http://static.zybuluo.com/usiege/0fsowyqvltk65wv4jw6ry9nv/image_1ce2rdqtlc7enklrrs1qacqu19.png" alt="TextKit WWDC2013 Session 210"></p></blockquote><h2 id="再搞清楚架构"><a href="#再搞清楚架构" class="headerlink" title="再搞清楚架构"></a>再搞清楚架构</h2><blockquote><p><img src="http://static.zybuluo.com/usiege/c3g4vjcpthekoavncaatrqxg/image_1ce2riahv1fl7186h1elefbfebsm.png" alt="重要的几个类"></p></blockquote><blockquote><ol><li>TextKit框架主要的几个View,主要包括<code>UILabel</code>, <code>UITextView</code>, <code>UITextField</code>;</li><li>TextKit是NS一支的,所以不光只在iOS中使用;</li><li>Text container对应<code>NSTextContainer</code>,它定义了文本排版区域,很明显,文字是在这个区域中被管理的;</li><li>Text storage对应<code>NSTextStorage</code>,继承自<code>NSMutableAttributedString</code>,用于存储文本字形和相关属性;</li><li>Layout manager对应<code>NSLayoutManager</code>,负责对文字进行编辑排版处理,在上面第4条中的类保存的数据可以通过本条中的类转换显示到视图中,其中这个单词字形(glyphs)需注意;</li></ol></blockquote><h2 id="这张图很直观"><a href="#这张图很直观" class="headerlink" title="这张图很直观"></a>这张图很直观</h2><blockquote><p><img src="http://static.zybuluo.com/usiege/gu22cm1i3tmchnk0amc0c9qg/image_1ce2t9vjp4o4roq1nj61m6h1kra13.png" alt="UITextView composition"></p></blockquote><h2 id="我们来做点事情"><a href="#我们来做点事情" class="headerlink" title="我们来做点事情"></a>我们来做点事情</h2><p>首先我们需要一个自定义类型的<code>UITextView</code>,用它来对我们的文字内容进行自定义修改;<br><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ProblemView</span>: <span class="title">UITextView</span> </span>{</span><br><span class="line"> <span class="keyword">override</span> <span class="keyword">init</span>(frame: <span class="type">CGRect</span>, textContainer: <span class="type">NSTextContainer</span>?) {</span><br><span class="line"> <span class="keyword">super</span>.<span class="keyword">init</span>(frame: frame, textContainer: textContainer)</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">required</span> <span class="keyword">init</span>?(coder aDecoder: <span class="type">NSCoder</span>) {</span><br><span class="line"> <span class="built_in">fatalError</span>(<span class="string">"init(coder:) has not been implemented"</span>)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p><img src="http://static.zybuluo.com/usiege/9fk86ry3v21fqmc33y91p9xu/image_1ce5b0af015ldu4f476hvv1bhn2g.png" alt="image_1ce5b0af015ldu4f476hvv1bhn2g.png-114.8kB"></p><p><code>UITextView</code>的初始化方法中有一个<code>textContainer</code>参数,很明显是我们上面提到的,且如图中三种颜色的框框所示,是我们上面提到的管理类,且全部为只读属性;<br>并且就上面的三种类之前的管理,如果我们要自己管理的话,应该也是一个树型的结构;</p><p>接下来我们要配合<code>NSAttributedString</code>添加显示强大的富文本;</p><h3 id="NSAttributedString"><a href="#NSAttributedString" class="headerlink" title="NSAttributedString"></a>NSAttributedString</h3><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span>(<span class="keyword">set</span>) <span class="keyword">var</span> attributedProblem: <span class="type">NSAttributedString</span> = <span class="type">NSAttributedString</span>.<span class="keyword">init</span>()</span><br><span class="line">{</span><br><span class="line"> <span class="keyword">willSet</span> {</span><br><span class="line"> <span class="keyword">self</span>.text = newValue.string</span><br><span class="line"> <span class="keyword">self</span>.font = font <span class="comment">//字体是会影响宽度的,所以该项如果是在外部设置的话,应该提前修改</span></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">self</span>.textContainer.lineBreakMode = .byWordWrapping</span><br><span class="line"> <span class="keyword">self</span>.textStorage.replaceCharacters(<span class="keyword">in</span>: <span class="type">NSRange</span>(location: <span class="number">0</span>, length: newValue.length), with: newValue)</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">let</span> size = <span class="keyword">self</span>.sizeThatFits(<span class="type">CGSize</span>(width: <span class="keyword">self</span>.bounds.width, height: <span class="type">CGFloat</span>(<span class="type">MAXFLOAT</span>)))</span><br><span class="line"> <span class="keyword">self</span>.textContainer.size = size</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">didSet</span> {</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>我们需要一个具有计算属性的变量,当我们在内部修改该变量时做一些操作;上面的代码解释几点:</p><ul><li>我们需要在替换textview内容的时候重新计算内部空间,所以必须要在计算前将内容复制下来;上面代码第4行;</li><li>第7行中我们给出了一个示范,在这里可以修改与<code>NSTextContainer</code>相关的属性;</li><li>第8行我们开始进行文本替换,替换的内容为设置的新的富文本内容,范围则是该文本的<code>NSRange</code>;</li><li>接下来我们需要重新计算内部大小,这个内容大小就类似于<code>ScrollView</code>的<code>contentSize</code>,计算的过程中我们要指定它的宽度,令高为最大值,结果会根据宽度计算出相应的文本需要高度;最后将size设置为<code>textContainer</code>的size,这里一定要注意;</li><li>这里如果是<code>self.sizeToFit()</code>方法,则<code>textView</code>的size会根据内容变大,而不是内部空间变大,这是与上面一条的区别;</li></ul><h3 id="那传一段文本进来吧"><a href="#那传一段文本进来吧" class="headerlink" title="那传一段文本进来吧"></a>那传一段文本进来吧</h3><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//设置题目文字属性</span></span><br><span class="line">func setupSubject(text: String, <span class="attribute">font</span>: UIFont) {</span><br><span class="line"> </span><br><span class="line"> let changeString = NSMutableAttributedString.init(string: text)</span><br><span class="line"> let desTextRange = NSRange(location: <span class="number">0</span>, length: text.count)</span><br><span class="line"> changeString.addAttribute(NSAttributedStringKey<span class="selector-class">.font</span>, value: <span class="attribute">font</span>, range: desTextRange)</span><br><span class="line"> changeString.addAttribute(NSAttributedStringKey<span class="selector-class">.foregroundColor</span>, value: UIColor<span class="selector-class">.blue</span>, range: desTextRange)</span><br><span class="line"> </span><br><span class="line"> self<span class="selector-class">.font</span> = <span class="attribute">font</span></span><br><span class="line"></span><br><span class="line"> self<span class="selector-class">.attributedProblem</span> = changeString</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>如果你以前用过富文本,那这个方法看起来没什么,无非就是做了两件事:</p><ol><li>生成一个富文本;(有关于富文本的内容,可以自行谷歌一车)</li><li>将文本设置到我们的textview里;</li></ol><h3 id="我想改变一段文字"><a href="#我想改变一段文字" class="headerlink" title="我想改变一段文字"></a>我想改变一段文字</h3><p>如果我们想修改某一截文字的属性,那么我们只需要将保存的富文本取出,然后截取位置,替换掉原先的富文本,然后重新设置到属性中去,如下:<br><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//当前要发生替换的区域</span></span><br><span class="line"><span class="keyword">private</span>(<span class="keyword">set</span>) <span class="keyword">var</span> optionsRange: <span class="type">NSRange</span>?</span><br><span class="line"><span class="comment">//替换选项文字</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">replaceOption</span><span class="params">(options: String, replaceOptions: String, font: UIFont)</span></span> {</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//给选项添加属性</span></span><br><span class="line"> <span class="keyword">let</span> changeString = <span class="type">NSMutableAttributedString</span>.<span class="keyword">init</span>(attributedString: <span class="keyword">self</span>.attributedProblem)</span><br><span class="line"> <span class="keyword">let</span> optionString = <span class="keyword">self</span>.textOptions(text: replaceOptions, font: font)</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//选项最终位置</span></span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">let</span> optionsRange = changeString.string.range(of: options) {</span><br><span class="line"> <span class="keyword">let</span> range = <span class="type">NSRange</span>(optionsRange, <span class="keyword">in</span>: options)</span><br><span class="line"> changeString.replaceCharacters(<span class="keyword">in</span>: range, with: optionString)</span><br><span class="line"> <span class="keyword">self</span>.optionsRange = range</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">self</span>.optionsRange = <span class="type">NSRange</span>(location: <span class="number">0</span>, length: <span class="number">0</span>)</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">self</span>.attributedProblem = changeString</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>当然我们要替换的文本当然也可以是富文本;<br><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//上面的第8行中的方法</span></span><br><span class="line"> <span class="comment">//给选项添加属性</span></span><br><span class="line"> <span class="function"><span class="keyword">func</span> <span class="title">textOptions</span><span class="params">(text: String, font: UIFont)</span></span> -> <span class="type">NSAttributedString</span> {</span><br><span class="line"> <span class="comment">//选项左右添加空格</span></span><br><span class="line"> <span class="keyword">let</span> addSpace = <span class="string">" "</span> + text + <span class="string">" "</span></span><br><span class="line"> </span><br><span class="line"> <span class="comment">//选项文字属性</span></span><br><span class="line"> <span class="keyword">let</span> optionString = <span class="type">NSMutableAttributedString</span>(string: addSpace)</span><br><span class="line"> <span class="keyword">let</span> optionRange = <span class="type">NSRange</span>(location: <span class="number">2</span>, length: text.<span class="built_in">count</span>)</span><br><span class="line"> </span><br><span class="line"> optionString.addAttribute(<span class="type">NSAttributedStringKey</span>.font, value: font.withSize(<span class="number">20</span>), range: optionRange)</span><br><span class="line"> optionString.addAttribute(<span class="type">NSAttributedStringKey</span>.foregroundColor, value: <span class="type">UIColor</span>.red, range: optionRange)</span><br><span class="line"> optionString.addAttribute(<span class="type">NSAttributedStringKey</span>.strokeColor, value: <span class="type">UIColor</span>.white, range: optionRange)</span><br><span class="line"> optionString.addAttribute(<span class="type">NSAttributedStringKey</span>.strokeWidth, value: -<span class="number">3</span>, range: optionRange)</span><br><span class="line"> optionString.addAttribute(<span class="type">NSAttributedStringKey</span>.underlineStyle, value: <span class="number">1</span>, range: optionRange)</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> optionString</span><br><span class="line"> }</span><br></pre></td></tr></table></figure></p><p>这里需要注意的就是swift-<code>Range</code>与oc-<code>NSRange</code>的转换,关于swift的<code>Range</code>个人感觉比以前难用了,但是更加通用了吧,说下转换:</p><figure class="highlight nimrod"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> <span class="keyword">let</span> optionsRange = changeString.<span class="built_in">string</span>.<span class="built_in">range</span>(<span class="keyword">of</span>: options) {</span><br><span class="line"> <span class="keyword">let</span> <span class="built_in">range</span> = <span class="type">NSRange</span>(optionsRange, <span class="keyword">in</span>: options)</span><br><span class="line"> changeString.replaceCharacters(<span class="keyword">in</span>: <span class="built_in">range</span>, <span class="keyword">with</span>: optionString)</span><br><span class="line"> self.optionsRange = <span class="built_in">range</span></span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line"> self.optionsRange = <span class="type">NSRange</span>(location: <span class="number">0</span>, length: <span class="number">0</span>)</span><br><span class="line">}</span><br><span class="line">//这里我把发生替换的部分用变量保存了下来</span><br></pre></td></tr></table></figure><h3 id="也许还可以替换图片"><a href="#也许还可以替换图片" class="headerlink" title="也许还可以替换图片"></a>也许还可以替换图片</h3><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//添加富文本图片</span></span><br><span class="line"><span class="comment">// originString 原始字符串</span></span><br><span class="line"><span class="comment">// replaceRange 要替换的文字范围</span></span><br><span class="line"><span class="comment">// size 替换图片大小</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">replacePictureForText</span><span class="params">(originString: NSAttributedString, replaceRange: NSRange, size: CGSize)</span></span> -> <span class="type">NSAttributedString</span> {</span><br><span class="line"> <span class="keyword">let</span> attachment = <span class="type">NSTextAttachment</span>()</span><br><span class="line"> attachment.image = <span class="type">UIImage</span>.<span class="keyword">init</span>(named: <span class="string">"study_select_words"</span>)</span><br><span class="line"> attachment.bounds = <span class="type">CGRect</span>(x: <span class="number">0</span>, y: <span class="number">0</span>, width: size.width, height: size.height)</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//最终结果</span></span><br><span class="line"> <span class="keyword">let</span> originMutiString = <span class="type">NSMutableAttributedString</span>.<span class="keyword">init</span>(attributedString: originString)</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//生成图片</span></span><br><span class="line"> <span class="keyword">let</span> attachString = <span class="type">NSAttributedString</span>(attachment: attachment)</span><br><span class="line"> <span class="keyword">let</span> mutiAttachString = <span class="type">NSMutableAttributedString</span>(attributedString: attachString)</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//替换成图片</span></span><br><span class="line"> originMutiString.replaceCharacters(<span class="keyword">in</span>: replaceRange, with: mutiAttachString)</span><br><span class="line"> <span class="keyword">return</span> originMutiString</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>无他,仍然只是需要找到一个替换区域,替换成想要的可支持的富文本属性;</p><h3 id="别人不会告诉你的事"><a href="#别人不会告诉你的事" class="headerlink" title="别人不会告诉你的事"></a>别人不会告诉你的事</h3><p>最后想告诉你我们可以通过<code>NSRange</code>来得到所在区域的坐标,这是个无意中谷歌到的东西,如下:<br><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> rect = <span class="keyword">self</span>.problem.textContainer.layoutManager?.boundingRect(forGlyphRange: <span class="keyword">self</span>.problem.optionsRange!,<span class="keyword">in</span>: <span class="keyword">self</span>.problem.textContainer)</span><br><span class="line"></span><br><span class="line"><span class="keyword">self</span>.problem.scrollRangeToVisible(<span class="keyword">self</span>.problem.optionsRange!)</span><br></pre></td></tr></table></figure></p><p>找到目标区域,并定位到该区域;</p><h2 id="以上。。。"><a href="#以上。。。" class="headerlink" title="以上。。。"></a>以上。。。</h2>]]></content>
<summary type="html">
<p>搞事情,就是要搞事情!</p>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="swift" scheme="http://charlesblog.site/tags/swift/"/>
<category term="iOS" scheme="http://charlesblog.site/tags/iOS/"/>
</entry>
<entry>
<title>为你的UIView添加一个动画Layer</title>
<link href="http://charlesblog.site/2018/05/21/%E4%B8%BA%E4%BD%A0%E7%9A%84UIView%E6%B7%BB%E5%8A%A0%E4%B8%80%E4%B8%AA%E5%8A%A8%E7%94%BBLayer/"/>
<id>http://charlesblog.site/2018/05/21/为你的UIView添加一个动画Layer/</id>
<published>2018-05-21T14:37:00.000Z</published>
<updated>2018-05-22T01:28:27.385Z</updated>
<content type="html"><![CDATA[<p>我想你一定用过UIView, 我想你也一定知道CALayer是什么,具体细节的东西请自行谷歌,我们今天要用Layer搞一点事情;</p><a id="more"></a><p>[TOC]</p><h2 id="总结几点性质"><a href="#总结几点性质" class="headerlink" title="总结几点性质"></a>总结几点性质</h2><blockquote><ol><li>UIView继承自<code>UIResponder</code>,用于交互,那么这么看来师承自事件流,属于动作学派;</li><li>UIView有一个<code>CALayer</code>的属性,且CALayer继承自<code>NSObject</code>,并且根据苹果文档描述”The base layer class”,看来应该是一个layer体系,且layer用于渲染,属于CA阵营,属于图像学派;</li><li>layer的代理是view,这样看来真正用于显示的应该是CALayer,鬼知道CALayer是不是跟OpenGL有关系;</li><li>所以如果你要是想做动画,那我给你的建议就是,最好在layer层上做;</li><li>对于,你知道layer是有个叫做<code>anchorPoint</code>属性的,做过cocos2dx的应该知道,你说layer的display里难道没有点opengl的痕迹?</li><li>还记得仿射变换吗,平移+线性变换,layer完全是可以做到的;</li><li>layer自身是有绘制能力的,只不过不支持事件响应,但有一点它可以做的到:layer遵从了一个<code>CAMediaTiming</code>的协议,而这个协议就厉害了,配合<code>CACurrentMediaTime</code>,跟系统时钟挂上勾,CPU的时钟周期<code>mach_absolute_time</code>转化成秒数的结果,是一个绝对时间;</li></ol></blockquote><h2 id="上面的结论是瞎扯淡"><a href="#上面的结论是瞎扯淡" class="headerlink" title="上面的结论是瞎扯淡"></a>上面的结论是瞎扯淡</h2><h2 id="我们来搞点看的见的"><a href="#我们来搞点看的见的" class="headerlink" title="我们来搞点看的见的"></a>我们来搞点看的见的</h2><ul><li>声明一个View:</li></ul><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CircleView</span>: <span class="title">UIView</span> </span>{</span><br><span class="line"> <span class="comment">//我要做一个绕圈的动画</span></span><br><span class="line"> <span class="comment">//我不会告诉你我是谷歌过的</span></span><br><span class="line"> <span class="comment">//我觉得你也应该学会</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li><p>添加两个Layer,如果不够,那就多来几个:</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> backgroundLayer: <span class="type">CAShapeLayer</span>?</span><br><span class="line"><span class="keyword">var</span> animationLayer: <span class="type">CAShapeLayer</span>?</span><br><span class="line"><span class="comment">//我觉得你应该知道把它们放在哪</span></span><br><span class="line"><span class="comment">//好吧我还是给你代码对齐吧,这很python</span></span><br></pre></td></tr></table></figure></li><li><p>工厂一个方法啊哟喂,设计模式就出来了:</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//给我点颜色,我给你想要的</span></span><br><span class="line"><span class="comment">//当然,我给你的并不多;</span></span><br><span class="line"><span class="comment">//我只是一个CAShapeLayer,有形状的框框;</span></span><br><span class="line"><span class="comment">//有边,有填充;</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">layer</span><span class="params">(lineColor: UIColor)</span></span> -> <span class="type">CAShapeLayer</span> {</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">let</span> layer = <span class="type">CAShapeLayer</span>()</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">let</span> lineWidth: <span class="type">CGFloat</span> = <span class="number">5</span></span><br><span class="line"> <span class="keyword">let</span> rect = <span class="type">CGRect</span>(x: <span class="number">0</span>, y: <span class="number">0</span>, width: <span class="keyword">self</span>.bounds.width, height: <span class="keyword">self</span>.bounds.height)</span><br><span class="line"> layer.bounds = rect</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//这是个圆</span></span><br><span class="line"> <span class="keyword">let</span> path = <span class="type">UIBezierPath</span>(roundedRect: rect, cornerRadius: rect.width / <span class="number">2</span>)</span><br><span class="line"> layer.lineWidth = lineWidth</span><br><span class="line"> layer.position = <span class="type">CGPoint</span>(x: rect.width / <span class="number">2</span>, y: rect.height / <span class="number">2</span>)</span><br><span class="line"> </span><br><span class="line"> layer.path = path.cgPath</span><br><span class="line"> layer.fillColor = <span class="type">UIColor</span>.clear.cgColor</span><br><span class="line"> layer.strokeColor = lineColor.cgColor</span><br><span class="line"> </span><br><span class="line"> layer.strokeStart = <span class="number">0</span></span><br><span class="line"> layer.strokeEnd = <span class="number">1</span></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> layer</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>加到view上来</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">override</span> <span class="keyword">init</span>(frame: <span class="type">CGRect</span>) {</span><br><span class="line"> <span class="keyword">super</span>.<span class="keyword">init</span>(frame: frame)</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">let</span> bgLayer = <span class="keyword">self</span>.layer(lineColor: <span class="type">UIColor</span>.green)</span><br><span class="line"> <span class="keyword">self</span>.layer.addSublayer(bgLayer)</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">self</span>.backgroundLayer = bgLayer</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">let</span> animationLayer = <span class="keyword">self</span>.layer(lineColor: <span class="type">UIColor</span>.orange)</span><br><span class="line"> <span class="keyword">self</span>.layer.addSublayer(animationLayer)</span><br><span class="line"> animationLayer.isHidden = <span class="literal">true</span></span><br><span class="line"> <span class="comment">//关于这个层,我们呆会还要做点其他事情;</span></span><br><span class="line"> <span class="comment">//暂时,它是不被看的到的;</span></span><br><span class="line"> <span class="comment">//所以你可以看到,一个View上是可以添加好多层的;</span></span><br><span class="line"> <span class="comment">//如果你把这些层分区块排列出来,那么我便不加那么多view了;</span></span><br><span class="line"> <span class="comment">//哈哈哈,上面这行我开个玩笑;</span></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">self</span>.animationLayer = animationLayer</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">self</span>.backgroundColor = <span class="type">UIColor</span>.black</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">required</span> <span class="keyword">init</span>?(coder aDecoder: <span class="type">NSCoder</span>) {</span><br><span class="line"> <span class="built_in">fatalError</span>(<span class="string">"init(coder:) has not been implemented"</span>)</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><h2 id="我们来加一个动画吧!"><a href="#我们来加一个动画吧!" class="headerlink" title="我们来加一个动画吧!"></a>我们来加一个动画吧!</h2><ul><li>添加动画</li></ul><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="type">PLAY_ANIMATION_KEY</span> = <span class="string">"animation_key"</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">startAnimation</span><span class="params">(totalTime: CGFloat)</span></span> {</span><br><span class="line"> <span class="keyword">guard</span> totalTime > <span class="number">0</span> <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">return</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">guard</span> ((<span class="keyword">self</span>.animationLayer?.animation(forKey: <span class="type">PLAY_ANIMATION_KEY</span>)) == <span class="literal">nil</span>) <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">return</span></span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">let</span> animation = <span class="type">CABasicAnimation</span>(keyPath: <span class="string">"strokeEnd"</span>)</span><br><span class="line"> animation.duration = <span class="type">CFTimeInterval</span>(totalTime)</span><br><span class="line"> </span><br><span class="line"> animation.delegate = <span class="keyword">self</span> <span class="comment">//转到它开始动了</span></span><br><span class="line"> </span><br><span class="line"> animation.fromValue = <span class="number">0</span></span><br><span class="line"> animation.toValue = <span class="number">1</span></span><br><span class="line"> </span><br><span class="line"> animation.isRemovedOnCompletion = <span class="literal">true</span></span><br><span class="line"> animation.fillMode = kCAFillModeForwards</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">self</span>.animationLayer?.add(animation, forKey: <span class="type">PLAY_ANIMATION_KEY</span>)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol><li>上面的我们解释一下,首先我们说一个动画是有名字的,用key表示,像上面的<code>PLAY_ANIMATION_KEY</code>;</li><li>layer添加的动画是<code>CAAnimation</code>类型的,就是说,所有它的子类都可以添加为layer的动画,你可以去挖掘一下<code>CAAnimation</code>一族;</li><li><code>CABasicAnimation</code>添加的动画是需要一个<code>keyPath</code>的,你还需要通过-setFromValue 和-setToValue 来指定一个开始值和结束值,这有点像一个补间动画,输入了起始帧和结束帧,其它马由动画帮你;<blockquote><p><img src="http://static.zybuluo.com/usiege/cy71tbwdl9q3ckokbr8hbqhb/image_1ce1gopv01m4lbd41tjr1nel6e39.png" alt="image_1ce1gopv01m4lbd41tjr1nel6e39.png-165.6kB"></p></blockquote></li><li>我们可以指定CALayer的某个属性名为keyPath,并且对CALayer的这个属性的值进行修改,达到相应的动画效果,随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue,keyPath内容是CALayer的可动画Animatable属性,关于这个可动画属性,我觉得我还可以去谷歌一车,回头再说吧;</li><li>如果<code>fillMode == kCAFillModeForwards</code>同时<code>removedOnComletion == false</code>,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变;</li></ol><h2 id="它开始动了"><a href="#它开始动了" class="headerlink" title="它开始动了"></a>它开始动了</h2><p>加入到layer中它会自动开始,并且这开始和结束都有回调哦;<br><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">extension</span> <span class="title">CircleView</span>: <span class="title">CAAnimationDelegate</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">func</span> <span class="title">animationDidStart</span><span class="params">(<span class="number">_</span> anim: CAAnimation)</span></span> {</span><br><span class="line"> <span class="keyword">self</span>.startTime = <span class="type">CACurrentMediaTime</span>()</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">func</span> <span class="title">animationDidStop</span><span class="params">(<span class="number">_</span> anim: CAAnimation, finished flag: Bool)</span></span> {</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h2 id="暂停和恢复"><a href="#暂停和恢复" class="headerlink" title="暂停和恢复"></a>暂停和恢复</h2><p>我们来记录两个时间:<br><figure class="highlight swift"><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"><span class="keyword">var</span> startTime: <span class="type">CFTimeInterval</span>! <span class="comment">//动画开始时系统时钟</span></span><br><span class="line"><span class="keyword">var</span> pastTime: <span class="type">CFTimeInterval</span>! <span class="comment">//动画运行过的时间(除去暂停的时间)</span></span><br></pre></td></tr></table></figure></p><ul><li>暂停一下<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">pauseAnimation</span><span class="params">(layer: CALayer)</span></span> {</span><br><span class="line"> <span class="keyword">let</span> pausetime = layer.convertTime(<span class="type">CACurrentMediaTime</span>(), from: <span class="literal">nil</span>)</span><br><span class="line"> layer.timeOffset = pausetime</span><br><span class="line"> layer.speed = <span class="number">0</span></span><br><span class="line"> </span><br><span class="line"> <span class="built_in">print</span>(#function)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"start time: \(startTime)"</span>)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"pause time: \(pausetime)"</span>)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"系统时钟: \(CACurrentMediaTime())"</span>)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"以GMT为标准的,2001年一月一日00:00:00这一刻的时间绝对值: \(CFAbsoluteTimeGetCurrent())"</span>)</span><br><span class="line"> <span class="keyword">let</span> pasttime = pausetime - startTime</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"past time: \(pasttime)"</span>)</span><br><span class="line"> <span class="keyword">self</span>.pastTime = pasttime</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><p>所以你只需要搞清楚<code>timeOffset</code>,<code>speed</code>以及<code>convertTime</code>就可以了;<br>按我说的做,自己跑一跑,对比下时间,马上清楚,不要再记些什么公式了;</p><ul><li>恢复动画<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">func resumeAnimation(layer: CALayer) {</span><br><span class="line"> let pausetime = layer.timeOffset</span><br><span class="line"> </span><br><span class="line"> layer.timeOffset = 0</span><br><span class="line"> layer.beginTime = 0</span><br><span class="line"> layer.speed = 1</span><br><span class="line"> </span><br><span class="line"> let begintime = layer.convertTime(CACurrentMediaTime(), to: nil) - pausetime</span><br><span class="line"> layer.beginTime = begintime</span><br><span class="line"> </span><br><span class="line"> print(#function)</span><br><span class="line"> print("系统时钟: \(CACurrentMediaTime())")</span><br><span class="line"> print("begin time: \(begintime)")</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><p>那么上面说的需要知道的属性还需要添加一个<code>beginTime</code>;</p><ul><li>最后你需要把动画移除掉吗?<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">stopAnimation</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="keyword">guard</span> <span class="keyword">self</span>.animationLayer?.animation(forKey: <span class="type">PLAY_ANIMATION_KEY</span>) != <span class="literal">nil</span> <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">return</span></span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="type">CATransaction</span>.begin()</span><br><span class="line"> <span class="type">CATransaction</span>.setDisableActions(<span class="literal">true</span>)</span><br><span class="line"> <span class="keyword">self</span>.animationLayer?.timeOffset = <span class="number">0</span></span><br><span class="line"> <span class="keyword">self</span>.animationLayer?.speed = <span class="number">1</span></span><br><span class="line"> <span class="keyword">self</span>.animationLayer?.beginTime = <span class="type">CACurrentMediaTime</span>()</span><br><span class="line"> <span class="keyword">self</span>.animationLayer?.strokeStart = <span class="number">0</span></span><br><span class="line"> <span class="keyword">self</span>.animationLayer?.strokeEnd = <span class="number">1</span></span><br><span class="line"> <span class="type">CATransaction</span>.commit()</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">self</span>.animationLayer?.removeAnimation(forKey: <span class="type">PLAY_ANIMATION_KEY</span>)</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><p>移除我们能看的懂,那么<code>CATransaction</code>呢?</p><h2 id="CATransaction?"><a href="#CATransaction?" class="headerlink" title="CATransaction?"></a>CATransaction?</h2><p>再去谷歌一车吧!!!</p>]]></content>
<summary type="html">
<p>我想你一定用过UIView, 我想你也一定知道CALayer是什么,具体细节的东西请自行谷歌,我们今天要用Layer搞一点事情;</p>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="swift" scheme="http://charlesblog.site/tags/swift/"/>
<category term="iOS" scheme="http://charlesblog.site/tags/iOS/"/>
</entry>
<entry>
<title>我们来探讨一下函数式编程</title>
<link href="http://charlesblog.site/2018/05/16/%E6%88%91%E4%BB%AC%E6%9D%A5%E6%8E%A2%E8%AE%A8%E4%B8%80%E4%B8%8B%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B/"/>
<id>http://charlesblog.site/2018/05/16/我们来探讨一下函数式编程/</id>
<published>2018-05-16T14:08:45.000Z</published>
<updated>2018-05-17T02:05:22.294Z</updated>
<content type="html"><![CDATA[<p>看了一本叫swift函数式编程的书,第一章就问题引入讨论了一下这个思想,我们来自己理解一下;首先上图,写一下传统做法;<br><a id="more"></a></p><h2 id="首先我们按照书中的定义"><a href="#首先我们按照书中的定义" class="headerlink" title="首先我们按照书中的定义"></a>首先我们按照书中的定义</h2><figure class="highlight swift"><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"><span class="keyword">typealias</span> <span class="type">Position</span> = <span class="type">CGPoint</span></span><br><span class="line"><span class="keyword">typealias</span> <span class="type">Distance</span> = <span class="type">CGFloat</span></span><br></pre></td></tr></table></figure><p>不懂<em>typealias</em>的请自行查阅;</p><h2 id="我们总是这样做"><a href="#我们总是这样做" class="headerlink" title="我们总是这样做"></a>我们总是这样做</h2><ol><li><p>图1所示,我们现在要表示一个未知点point是否在图中黑色圈圈内,很自然的,我们传入point参数,返回一个bool值,来解决这个问题,通常我们都会这样思考;<br><img src="http://static.zybuluo.com/usiege/ku12muk4e3itce31patxdjdu/291212487821245.png" alt="inRange1"></p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">inRange1</span><span class="params">(target: Position, range: Distance)</span></span> -> <span class="type">Bool</span> {</span><br><span class="line"> <span class="keyword">return</span> sqrt(target.x * target.x + target.y * target.y) <= range</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>那么如果我们的圆心不在(0,0)点呢,需要做坐标系仿射变换(线性变换加上一个平移变换)对吧,或者理解仿射有点吃力,我们只做平移变换,就是说现在我们原点不是(0,0)了:<br><img src="http://static.zybuluo.com/usiege/flzxd5sm0yjsedvsaiuwo31p/291235402204895.png" alt="inRange2"></p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">inRange2</span><span class="params">(target: Position, ownPosition: Position, range: Distance)</span></span> -> <span class="type">Bool</span> {</span><br><span class="line"> <span class="keyword">let</span> dx = ownPosition.x - target.x</span><br><span class="line"> <span class="keyword">let</span> dy = ownPosition.y - target.y</span><br><span class="line"> <span class="keyword">let</span> targetDistance = sqrt(pow(dx, <span class="number">2.0</span>) + pow(dy, <span class="number">2.0</span>))</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> targetDistance <= range</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ol><p>其实就是空间中的两个点得出一个相对距离,也很简单对吧,我们继续;</p><ol start="3"><li>现在我们又有新需求了,我们要挖去中间的这个圆,因为我们的点现在要在这个环上运动了:<br><img src="http://static.zybuluo.com/usiege/40zqog5p3vesuuk375hzg7iz/291247102209096.png" alt="inRange34"><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> minimumDistance: <span class="type">Distance</span> = <span class="number">2.0</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">inRange3</span><span class="params">(target: Position, ownPosition: Position, range: Distance)</span></span> -> <span class="type">Bool</span> {</span><br><span class="line"> <span class="keyword">let</span> dx = ownPosition.x - target.x</span><br><span class="line"> <span class="keyword">let</span> dy = ownPosition.y - target.y</span><br><span class="line"> <span class="keyword">let</span> targetDistance = sqrt(pow(dx, <span class="number">2.0</span>) + pow(dy, <span class="number">2.0</span>))</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> targetDistance <= range && targetDistance >= minimumDistance</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ol><p>就是需要我们挖去以原点为中心,半径为<code>minimumDistance</code>的圆,也还好;</p><ol start="4"><li>我们还要考虑如果有一个圆,让这个圆在小圆环之外;<br>如上图中<code>Friendly</code>所示;<figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">inRange4</span><span class="params">(target: Position, ownPosition: Position, friendly:Position, range: Distance)</span></span> -> <span class="type">Bool</span> {</span><br><span class="line"> <span class="keyword">let</span> dx = ownPosition.x - target.x</span><br><span class="line"> <span class="keyword">let</span> dy = ownPosition.y - target.y</span><br><span class="line"> <span class="keyword">let</span> targetDistance = sqrt(dx * dx + dy * dy)</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">let</span> friendlyDx = friendly.x - target.x</span><br><span class="line"> <span class="keyword">let</span> friendlyDy = friendly.y - target.y</span><br><span class="line"> <span class="keyword">let</span> friendlyDistance = sqrt(pow(friendlyDx, <span class="number">2.0</span>) + pow(friendlyDy, <span class="number">2.0</span>))</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> targetDistance <= range</span><br><span class="line"> && targetDistance >= minimumDistance</span><br><span class="line"> && friendlyDistance >= minimumDistance</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ol><h2 id="我们还可以这样做"><a href="#我们还可以这样做" class="headerlink" title="我们还可以这样做"></a>我们还可以这样做</h2><p>的确如书上所说,我做了好多重复的工作,而且从代码复制粘贴的情况来看,我似乎做了不少工作;太你太臃肿了,需要重构!<br>于是我们定义了这样一个关系,它是一个关系,也是一个值,作者说函数要当作是值来看待的;<br><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typealias</span> <span class="type">Region</span> = (<span class="type">Position</span>) -> <span class="type">Bool</span></span><br></pre></td></tr></table></figure></p><p>理解起来也很容易:我是一个函数,我接受一个参数,你可以将Position的点让我来帮你验证,如果你通过我的验证,那你就是我要表达的Region,我会告诉你你的参数是不是我要的结果;<br>很顺畅对吧!接下来我们用它来写几个函数:</p><ul><li><p>inRange1重写</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">circle</span><span class="params">(radius: Distance)</span></span> -> <span class="type">Region</span> {</span><br><span class="line"> <span class="keyword">return</span> { position <span class="keyword">in</span></span><br><span class="line"> sqrt(pow(position.x, <span class="number">2.0</span>) + pow(position.y, <span class="number">2.0</span>)) <= radius <span class="comment">//这不加 return 竟然也可以</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>inRange2重写,平移变换圆</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">shift</span><span class="params">(offset: Position, region: @escaping Region)</span></span> -> <span class="type">Region</span> {</span><br><span class="line"> <span class="keyword">return</span> { position <span class="keyword">in</span></span><br><span class="line"> <span class="keyword">return</span> region(<span class="type">Position</span>(x: position.x + offset.x, y: position.y + offset.y))</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>写一个不是我范围的Region</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">invert</span><span class="params">(region: @escaping Region)</span></span> -> <span class="type">Region</span> {</span><br><span class="line"> <span class="keyword">return</span> { position <span class="keyword">in</span></span><br><span class="line"> !region(position)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>来一个相交的区域</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">intersection</span><span class="params">(region1: Region, region2: Region)</span></span> -> <span class="type">Region</span> {</span><br><span class="line"> <span class="keyword">return</span> { point <span class="keyword">in</span></span><br><span class="line"> region1(point) && region2(point)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>来一个并集的区域</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">union</span><span class="params">(region1: Region, region2: Region)</span></span> -> <span class="type">Region</span> {</span><br><span class="line"> <span class="keyword">return</span> { point <span class="keyword">in</span></span><br><span class="line"> region1(point) || region2(point)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>再来一个差集</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//函数表示在region中,而属于minusRegion的部分</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">difference</span><span class="params">(region: Region, minusRegion: Region)</span></span> -> <span class="type">Region</span> {</span><br><span class="line"> <span class="keyword">return</span> intersection(region1: region, region2: invert(region: minusRegion))</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><p>一时间发现把集合的性质写了一个遍,那如果把这个东西写成一个泛型,用的岂不是更多?<br>先不考虑,我们来重新写一下之前的那个<code>inRange4</code>吧!</p><h2 id="最终inRange版本"><a href="#最终inRange版本" class="headerlink" title="最终inRange版本"></a>最终inRange版本</h2><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">inRange</span><span class="params">(ownPosition: Position, target: Position, friendly: Position, range: Distance)</span></span> -> <span class="type">Bool</span> {</span><br><span class="line"> <span class="comment">//表示灰色的圆环,顶点为(0,0)的圆环</span></span><br><span class="line"> <span class="keyword">let</span> rangeRegion = difference(region: circle(radius: range), minusRegion: circle(radius: minimumDistance))</span><br><span class="line"> <span class="comment">//发生了平移变换后的圆环</span></span><br><span class="line"> <span class="keyword">let</span> targetRegion = shift(offset: ownPosition, region: rangeRegion)</span><br><span class="line"> <span class="comment">//发生了平移变换后的朋友圈</span></span><br><span class="line"> <span class="keyword">let</span> friendlyRegion = shift(offset: friendly, region: circle(radius: minimumDistance))</span><br><span class="line"> <span class="comment">//最终结果为在目标圆环中,而不在朋友圈的区域</span></span><br><span class="line"> <span class="keyword">let</span> resultRegion = difference(region: targetRegion, minusRegion: friendlyRegion)</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> resultRegion(target)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="结论"><a href="#结论" class="headerlink" title="结论"></a>结论</h2><p>我不知道这过程中我做了什么,总的来说我貌似理解的更清晰了,改天再研究吧!你有什么想法,我们可以探讨一下啊!</p>]]></content>
<summary type="html">
<p>看了一本叫swift函数式编程的书,第一章就问题引入讨论了一下这个思想,我们来自己理解一下;首先上图,写一下传统做法;<br>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="swift" scheme="http://charlesblog.site/tags/swift/"/>
<category term="functional" scheme="http://charlesblog.site/tags/functional/"/>
</entry>
<entry>
<title>Mac下安装OpenMP并完成编译</title>
<link href="http://charlesblog.site/2018/05/13/Mac%E4%B8%8B%E5%AE%89%E8%A3%85OpenMP%E5%B9%B6%E5%AE%8C%E6%88%90%E7%BC%96%E8%AF%91/"/>
<id>http://charlesblog.site/2018/05/13/Mac下安装OpenMP并完成编译/</id>
<published>2018-05-12T16:47:28.000Z</published>
<updated>2018-05-14T03:19:31.502Z</updated>
<content type="html"><![CDATA[<p>OpenMP在Mac上的安装,涉及到一些编译器的历史。。。<br><a id="more"></a></p><h2 id="OpenMP环境添加-Mac"><a href="#OpenMP环境添加-Mac" class="headerlink" title="OpenMP环境添加(Mac)"></a>OpenMP环境添加(Mac)</h2><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></pre></td><td class="code"><pre><span class="line">$ brew reinstall gcc --without-multilib</span><br><span class="line"><span class="comment"># 安装支持openmp的clang</span></span><br><span class="line">$ brew install clang-omp <span class="comment">#有错</span></span><br></pre></td></tr></table></figure><h2 id="安装错误"><a href="#安装错误" class="headerlink" title="安装错误"></a>安装错误</h2><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># Problem: No available formula <span class="keyword">with</span> the name <span class="string">"clang-omp"</span></span><br><span class="line"></span><br><span class="line">ruby -e <span class="string">"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"</span> < <span class="regexp">/dev/</span><span class="literal">null</span> <span class="number">2</span>> <span class="regexp">/dev/</span><span class="literal">null</span></span><br></pre></td></tr></table></figure><p><a href="http://macappstore.org/clang-omp/" target="_blank" rel="noopener">安装错误参考</a>,用以上方法发现未解决问题;</p><blockquote><p>fatal: unable to access <a href="https://github.com/Homebrew/homebrew-core/" target="_blank" rel="noopener">https://github.com/Homebrew/homebrew-core</a>:<br>LibreSSL SSL_read: SSL_ERROR_SYSCALL, errno 54<br>Error: Fetching /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core failed!<br>Error: Could not link:<br>/usr/local/share/man/man1/brew.1</p></blockquote><blockquote><p>Please delete these paths and run <code>brew update</code>.<br>Error: Could not link:<br>/usr/local/share/doc/homebrew</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 删除 /usr/<span class="built_in">local</span>/Homebrew/Library/Taps/homebrew/homebrew-core 文件夹</span></span><br><span class="line"></span><br><span class="line"><span class="meta">$</span><span class="bash"> brew update</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> brew install clang-omp</span></span><br></pre></td></tr></table></figure><blockquote><p>fatal: unable to access ‘<a href="https://github.com/Homebrew/homebrew-core/'" target="_blank" rel="noopener">https://github.com/Homebrew/homebrew-core/'</a>: LibreSSL SSL_read: SSL_ERROR_SYSCALL, errno 54<br>Error: Failure while executing: git clone <a href="https://github.com/Homebrew/homebrew-core" target="_blank" rel="noopener">https://github.com/Homebrew/homebrew-core</a> /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core –depth=1<br>Error: Failure while executing: /usr/local/bin/brew tap homebrew/core</p></blockquote><figure class="highlight armasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">brew </span>doctor</span><br></pre></td></tr></table></figure><blockquote><p>Error: No available formula with the name “clang-omp”<br>==> Searching for a previously deleted formula (in the last month)…<br>Warning: homebrew/core is shallow clone. To get complete history run:<br> git -C “$(brew –repo homebrew/core)” fetch –unshallow</p></blockquote><blockquote><p>Error: No previously deleted formula found.<br>==> Searching for similarly named formulae…<br>==> Searching local taps…<br>Error: No similarly named formulae found.<br>==> Searching taps…<br>==> Searching taps on GitHub…<br>Error: No formulae found in taps.</p></blockquote><figure class="highlight asciidoc"><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">'''</span><br><span class="line">You need a recent version of llvm and libomp which you can get with</span><br><span class="line">'''</span><br><span class="line">$ brew install llvm</span><br><span class="line"># brew install libomp</span><br></pre></td></tr></table></figure><blockquote><p>On Apple Clang, you need to add several options to use OpenMP’s front end<br>instead of the standard driver option. This usually looks like<br> -Xpreprocessor -fopenmp -lomp</p></blockquote><blockquote><p>You might need to make sure the lib and include directories are discoverable<br>if /usr/local is not searched:<br>-L/usr/local/opt/libomp/lib -I/usr/local/opt/libomp/include</p></blockquote><blockquote><p>For CMake, the following flags will cause the OpenMP::OpenMP_CXX target to<br>be set up correctly:<br>-DOpenMP_CXX_FLAGS=”-Xpreprocessor -fopenmp -I/usr/local/opt/libomp/include”<br>-DOpenMP_CXX_LIB_NAMES=”omp”<br>-DOpenMP_omp_LIBRARY=/usr/local/opt/libomp/lib/libomp.dylib</p></blockquote><p>接下来发现libomp已经在我的lib库里了,定位:<em>/usr/local/opt/libomp</em>;<br>下面要做的事情就是终端到你写的.c文件下,输入以下命令编译;<br><figure class="highlight crystal"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">clang -Xclang -fopenmp openmp_test.c -I /usr/local/opt/libom/<span class="keyword">include</span> -L /usr/local/opt/libomp/<span class="class"><span class="keyword">lib</span> -<span class="title">lomp</span></span></span><br></pre></td></tr></table></figure></p><p>上面这个命令会链接头文件和动态库,我们想办法把这两个路径添加到环境变量里,每次都写路径很麻烦;</p><h2 id="Compiler"><a href="#Compiler" class="headerlink" title="Compiler"></a>Compiler</h2><figure class="highlight bash"><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">$ <span class="built_in">export</span> OMP_NUM_THREADS=4</span><br><span class="line">$ gcc -fopenmp filename.c</span><br></pre></td></tr></table></figure><p>因为我们要用clang来编译,所以上面的这个编译过程应该写为;</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> <span class="built_in">export</span> OMP_NUM_THREADS=4</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> clang -fopenmp filename.c -o filename</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> clang: error: unsupported option <span class="string">'-fopenmp'</span></span></span><br></pre></td></tr></table></figure><p>最终解决方案,Homebrew安装的GCC存放在 /usr/local/bin/gcc-5 中(GCC5.2.0版)。此时,系统中依然有 /usr/bin/gcc ,然而这个GCC是clang的链接。所以在编译时,需要使用类似 gcc-5 xxx.c -o xxx -fopenmp 进行编译,而不是使用默认的gcc。</p><p>所以只要我们用下面的编译方法就可以了:<br><figure class="highlight shell"><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"><span class="meta">$</span><span class="bash"> gcc-6 -fopenmp filename.c -o filename</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> ./filename <span class="comment">#执行吧!</span></span></span><br></pre></td></tr></table></figure></p><p>真的是绕了一圈,原来是llvm 与 gcc的历史问题;</p><h2 id="PS"><a href="#PS" class="headerlink" title="PS"></a>PS</h2><p>附1:测试程序</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><omp.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"><span class="meta">#<span class="meta-keyword">pragma</span> omp parallel</span></span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"Hello from thread %d, nthreads %d\n"</span>, omp_get_thread_num(), omp_get_num_threads());</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>附2: 继续找发现一个在Xcode上安装clang-omp安装的方法,未测试通过,慎用;</p><figure class="highlight bash"><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">$ brew install llvm</span><br><span class="line">$ <span class="built_in">echo</span> <span class="string">'export PATH="/usr/local/opt/llvm/bin:$PATH"'</span> >> ~/.bash_profile</span><br></pre></td></tr></table></figure><p><img src="http://static.zybuluo.com/usiege/voi9cducaj6qxf9gyj22j7o5/image_1cdaaol7q1a32nov11t4108hg4vm.png" alt="image_1cdaaol7q1a32nov11t4108hg4vm.png-115.1kB"></p>]]></content>
<summary type="html">
<p>OpenMP在Mac上的安装,涉及到一些编译器的历史。。。<br>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="Mac" scheme="http://charlesblog.site/tags/Mac/"/>
<category term="OpenMP" scheme="http://charlesblog.site/tags/OpenMP/"/>
</entry>
<entry>
<title>Hello World</title>
<link href="http://charlesblog.site/2018/05/07/hello-world/"/>
<id>http://charlesblog.site/2018/05/07/hello-world/</id>
<published>2018-05-07T02:17:42.733Z</published>
<updated>2018-05-07T02:17:42.733Z</updated>
<content type="html"><![CDATA[<p>Welcome to <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/" target="_blank" rel="noopener">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html" target="_blank" rel="noopener">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues" target="_blank" rel="noopener">GitHub</a>.<br><a id="more"></a></p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/writing.html" target="_blank" rel="noopener">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/server.html" target="_blank" rel="noopener">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/generating.html" target="_blank" rel="noopener">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/deployment.html" target="_blank" rel="noopener">Deployment</a></p>]]></content>
<summary type="html">
<p>Welcome to <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/" target="_blank" rel="noopener">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html" target="_blank" rel="noopener">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues" target="_blank" rel="noopener">GitHub</a>.<br>
</summary>
</entry>
<entry>
<title>你一定不知道Swift源码怎么看?</title>
<link href="http://charlesblog.site/2018/05/03/%E4%BD%A0%E4%B8%80%E5%AE%9A%E4%B8%8D%E7%9F%A5%E9%81%93Swift%E6%BA%90%E7%A0%81%E6%80%8E%E4%B9%88%E7%9C%8B%EF%BC%9F/"/>
<id>http://charlesblog.site/2018/05/03/你一定不知道Swift源码怎么看?/</id>
<published>2018-05-03T15:19:00.000Z</published>
<updated>2018-05-07T02:17:42.734Z</updated>
<content type="html"><![CDATA[<p>我想你一定是在开玩笑。<br>源码怎么看,打开看呗!说这话的时候请收下我的轻蔑,哈哈。不过就这个问题我今天在知乎搜索了一通。不要问我为什么在知乎搜索,鬼知道知乎什么都有。<br>那么,请收下我的提问:<br><a id="more"></a></p><blockquote><p><a href="https://www.zhihu.com/question/38215419" target="_blank" rel="noopener">如何阅读Swift源码</a></p></blockquote><p>知乎果然没有让我失望,结果教程如下;</p><blockquote><p><a href="http://swift.gg/2016/12/30/how-to-read-the-swift-standard-libray-source/" target="_blank" rel="noopener"># <a href="http://swift.gg/2016/12/30/how-to-read-the-swift-standard-libray-source/" title="如何阅读 Swift 标准库中的源码" target="_blank" rel="noopener">如何阅读 Swift 标准库中的源码</a></a></p></blockquote><p>顺便提一下,这次搜索还让我发现了一个比较不错的swift网站,有心的同学请收下:<a href="http://swift.gg" target="_blank" rel="noopener">swift.gg</a></p><p>于是今天搞了下源码的编译,并了解到一个叫做 <em>GYB</em> 的东西,这个东西今天先放一下。源碼編譯的過程無非就是用 <em>brew</em> 下了一些命令行軟件,然後使用 <em>build</em> 腳本跑一下過程,在此也不多說。但是今天的重點當然是我們要從源碼出發搞一些事情。<br>续:今天又build,发现也并没有得出什么重要的东西,只是把gyb文件生成为swift文件,其他过程不知道它经历了什么,对我想看源码没有任何作用,还跑了整整一个下午;对于只是想看代码的同学,还是用官网给出的gyb.py脚本做处理吧;</p><ol><li>hashable</li></ol><p>前两天写Dictionary时发现想用枚举做key,自定义一个Dictionary,value是#selector,但是在写的过程中发现说key值需要遵循hashable协议。可以看源码来理解一下。<br>首先要找到Hashable文件,发现swift的标准核心库被放在 <strong>stdlib/public/core</strong> 下,有一个 <strong>Hashable.swift</strong> 文件,打开文件先是一大段的描述,大体内容就是hashable协议作用的场景,以及给出了一个小例子;</p><p>一个Hash类型,提供了一个 hashValue 的属性,它是一个整型常量, 如果有两个相同类型的a,b,如果 a == b,那么 a.hashValue == b.hashValue;但是反过来,如果两个hash值相同,并不表示a 就一定等于 b;<br>还有一点非常重要,就是在两次不同的程序执行中hash值并不保证相等,所以不要把hash值用在你的程序中;<br>Hashable协议可用于struct, enum, class,它继承于 Equatable,所以遵循Hashable协议需要同时实现Hashable协议方法,以及 Equatable 协议方法;</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/// A point in an x-y coordinate system.</span></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">GridPoint</span> </span>{</span><br><span class="line"> <span class="keyword">var</span> x: <span class="type">Int</span></span><br><span class="line"> <span class="keyword">var</span> y: <span class="type">Int</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">extension</span> <span class="title">GridPoint</span>: <span class="title">Hashable</span> </span>{</span><br><span class="line"> <span class="keyword">var</span> hashValue: <span class="type">Int</span> {</span><br><span class="line"> <span class="keyword">return</span> x.hashValue ^ y.hashValue &* <span class="number">16777619</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">static</span> <span class="function"><span class="keyword">func</span> == <span class="params">(lhs: GridPoint, rhs: GridPoint)</span></span> -> <span class="type">Bool</span> {</span><br><span class="line"> <span class="keyword">return</span> lhs.x == rhs.x && lhs.y == rhs.y</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> tappedPoints: <span class="type">Set</span> = [<span class="type">GridPoint</span>(x: <span class="number">2</span>, y: <span class="number">3</span>), <span class="type">GridPoint</span>(x: <span class="number">4</span>, y: <span class="number">1</span>)]</span><br><span class="line"> <span class="keyword">let</span> nextTap = <span class="type">GridPoint</span>(x: <span class="number">0</span>, y: <span class="number">1</span>)</span><br><span class="line"> <span class="keyword">if</span> tappedPoints.<span class="built_in">contains</span>(nextTap) {</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"Already tapped at (\(nextTap.x), \(nextTap.y))."</span>)</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> tappedPoints.insert(nextTap)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"New tap detected at (\(nextTap.x), \(nextTap.y))."</span>)</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// Prints "New tap detected at (0, 1).")</span></span><br></pre></td></tr></table></figure><p>在实现的代码里有一些奇怪的符号,暂时还有点摸不清头脑,有些是一些编译符号,大体能看懂点意思,但有些像<code>@_silgen_name("_swift_stdlib_Hashable_isEqual_indirect")</code>就完全看不懂,回头找人再请教;<br>这里还要说的一个就是一个<code>UnsafePointer<T></code>:</p><blockquote><p>在 Swift 中,指针都使用一个特殊的类型来表示,那就是 UnsafePointer<t>。遵循了 Cocoa 的一贯不可变原则,UnsafePointer<t> 也是不可变的。当然对应地,它还有一个可变变体,UnsafeMutablePointer<t>。绝大部分时间里,C 中的指针都会被以这两种类型引入到 Swift 中:C 中 const 修饰的指针对应 UnsafePointer (最常见的应该就是 C 字符串的 const char * 了),而其他可变的指针则对应 UnsafeMutablePointer。除此之外,Swift 中存在表示一组连续数据指针的 UnsafeBufferPointer<t>,表示非完整结构的不透明指针 COpaquePointer 等等。另外你可能已经注意到了,能够确定指向内容的指针类型都是泛型的 struct,我们可以通过这个泛型来对指针指向的类型进行约束以提供一定安全性。</t></t></t></t></p></blockquote><p>需要具体了解的看这篇:<a href="https://onevcat.com/2015/01/swift-pointer/" target="_blank" rel="noopener">UnsafePointe<t></t></a></p><p>顺便吐槽句哈,apple的代码也还有这种东西,也不知道是修改过的没有;<br><img src="https://upload-images.jianshu.io/upload_images/1429775-225ee3ef5a38e747.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="FIXME"></p><ol start="2"><li>Equatable</li></ol><ul><li>它是一种可用于值比较的类型;</li><li>在序列和集合操作中,可以将一个遵循了<code>Equatable</code>协议的对象传递给<code>contaions(_:)</code>方法,来确定是否包含,用法如下:</li></ul><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> students = [<span class="string">"Nora"</span>, <span class="string">"Fern"</span>, <span class="string">"Ryan"</span>, <span class="string">"Rainer"</span>]</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> nameToCheck = <span class="string">"Ryan"</span></span><br><span class="line"><span class="keyword">if</span> students.<span class="built_in">contains</span>(nameToCheck) {</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"\(nameToCheck) is signed up!"</span>)</span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"No record of \(nameToCheck)."</span>)</span><br><span class="line">}</span><br><span class="line"> <span class="comment">// Prints "Ryan is signed up!"</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/// Conforming to the Equatable Protocol</span></span><br></pre></td></tr></table></figure><ul><li>本地类型继承自<code>Equatable</code>协议需要注意:<ol><li>对于一个<code>struct</code>类型,它的所有存储属性都需要遵循<code>Equatable</code>协议;</li><li>对于一个<code>enum</code>类型,它的所有关联值都需要遵循<code>Equatable</code>协议;</li><li>如果上述标准不符合,需要在扩展中实现<code>==</code>静态方法;<br>例如:</li></ol></li></ul><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">StreetAddress</span> </span>{</span><br><span class="line"> <span class="keyword">let</span> number: <span class="type">String</span></span><br><span class="line"> <span class="keyword">let</span> street: <span class="type">String</span></span><br><span class="line"> <span class="keyword">let</span> unit: <span class="type">String</span>?</span><br><span class="line"> <span class="keyword">init</span>(<span class="number">_</span> number: <span class="type">String</span>, <span class="number">_</span> street: <span class="type">String</span>, unit: <span class="type">String</span>? = <span class="literal">nil</span>) {</span><br><span class="line"> <span class="keyword">self</span>.number = number</span><br><span class="line"> <span class="keyword">self</span>.street = street</span><br><span class="line"> <span class="keyword">self</span>.unit = unit</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">extension</span> <span class="title">StreetAddress</span>: <span class="title">Equatable</span> </span>{</span><br><span class="line"> <span class="keyword">static</span> <span class="function"><span class="keyword">func</span> == <span class="params">(lhs: StreetAddress, rhs: StreetAddress)</span></span> -> <span class="type">Bool</span> {</span><br><span class="line"> <span class="keyword">return</span></span><br><span class="line"> lhs.number == rhs.number &&</span><br><span class="line"> lhs.street == rhs.street &&</span><br><span class="line"> lhs.unit == rhs.unit</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> addresses = [<span class="type">StreetAddress</span>(<span class="string">"1490"</span>, <span class="string">"Grove Street"</span>),</span><br><span class="line"> <span class="type">StreetAddress</span>(<span class="string">"2119"</span>, <span class="string">"Maple Avenue"</span>),</span><br><span class="line"> <span class="type">StreetAddress</span>(<span class="string">"1400"</span>, <span class="string">"16th Street"</span>)]</span><br><span class="line"><span class="keyword">let</span> home = <span class="type">StreetAddress</span>(<span class="string">"1400"</span>, <span class="string">"16th Street"</span>)</span><br><span class="line"><span class="built_in">print</span>(addresses[<span class="number">0</span>] == home)</span><br><span class="line"><span class="comment">// Prints "false"</span></span><br><span class="line"><span class="built_in">print</span>(addresses.<span class="built_in">contains</span>(home))</span><br><span class="line"><span class="comment">// Prints "true"</span></span><br></pre></td></tr></table></figure><ul><li>另外我在这个实现里面看到了以前数学课知识的身影:</li></ul><ul><li><code>a == a</code> is always <code>true</code> (Reflexivity) # 自反性</li><li><code>a == b</code> implies <code>b == a</code> (Symmetry) # 对称性</li><li><code>a == b</code> and <code>b == c</code> implies <code>a == c</code> (Transitivity) # 传递性<br>所以我们定义的<code>==</code>(两对象相等)完全取决于我们自己实现的静态方法:</li></ul><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">IntegerRef</span>: <span class="title">Equatable</span> </span>{</span><br><span class="line"> <span class="keyword">let</span> value: <span class="type">Int</span></span><br><span class="line"> <span class="keyword">init</span>(<span class="number">_</span> value: <span class="type">Int</span>) {</span><br><span class="line"> <span class="keyword">self</span>.value = value</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">static</span> <span class="function"><span class="keyword">func</span> == <span class="params">(lhs: IntegerRef, rhs: IntegerRef)</span></span> -> <span class="type">Bool</span> {</span><br><span class="line"> <span class="keyword">return</span> lhs.value == rhs.value</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">let</span> a = <span class="type">IntegerRef</span>(<span class="number">100</span>)</span><br><span class="line"><span class="keyword">let</span> b = <span class="type">IntegerRef</span>(<span class="number">100</span>)</span><br><span class="line"><span class="built_in">print</span>(a == a, a == b, separator: <span class="string">", "</span>)</span><br><span class="line"><span class="comment">// Prints "true, true"</span></span><br></pre></td></tr></table></figure><p>而不相等的定义则完全是,自实现的相等操作取反:</p><figure class="highlight less"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">extension</span> <span class="selector-tag">Equatable</span> {</span><br><span class="line"> <span class="comment">/// Returns a Boolean value indicating whether two values are not equal.</span></span><br><span class="line"> <span class="comment">///</span></span><br><span class="line"> <span class="comment">/// Inequality is the inverse of equality. For any values `a` and `b`, `a != b`</span></span><br><span class="line"> <span class="comment">/// implies that `a == b` is `false`.</span></span><br><span class="line"> <span class="comment">///</span></span><br><span class="line"> <span class="comment">/// This is the default implementation of the not-equal-to operator (`!=`)</span></span><br><span class="line"> <span class="comment">/// for any type that conforms to `Equatable`.</span></span><br><span class="line"> <span class="comment">///</span></span><br><span class="line"> <span class="comment">/// - Parameters:</span></span><br><span class="line"> <span class="comment">/// - lhs: A value to compare.</span></span><br><span class="line"> <span class="comment">/// - rhs: Another value to compare.</span></span><br><span class="line"> <span class="variable">@inlinable</span> <span class="comment">// FIXME(sil-serialize-all)</span></span><br><span class="line"> <span class="variable">@_transparent</span></span><br><span class="line"> public static func != (<span class="attribute">lhs</span>: Self, <span class="attribute">rhs</span>: Self) -> Bool {</span><br><span class="line"> <span class="selector-tag">return</span> !(lhs == rhs)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这个实现是已经定义好的!!!</p><ul><li><code>==</code>与<code>===</code>的区别<br>看一下这两者的区别:</li></ul><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">protocol</span> <span class="title">Equatable</span> </span>{</span><br><span class="line"> <span class="comment">/// Returns a Boolean value indicating whether two values are equal.</span></span><br><span class="line"> <span class="comment">///</span></span><br><span class="line"> <span class="comment">/// Equality is the inverse of inequality. For any values `a` and `b`,</span></span><br><span class="line"> <span class="comment">/// `a == b` implies that `a != b` is `false`.</span></span><br><span class="line"> <span class="comment">///</span></span><br><span class="line"> <span class="comment">/// - Parameters:</span></span><br><span class="line"> <span class="comment">/// - lhs: A value to compare.</span></span><br><span class="line"> <span class="comment">/// - rhs: Another value to compare.</span></span><br><span class="line"> <span class="keyword">static</span> <span class="function"><span class="keyword">func</span> == <span class="params">(lhs: <span class="keyword">Self</span>, rhs: <span class="keyword">Self</span>)</span></span> -> <span class="type">Bool</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">@inlinable <span class="comment">// FIXME(sil-serialize-all)</span></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">func</span> === <span class="params">(lhs: AnyObject?, rhs: AnyObject?)</span></span> -> <span class="type">Bool</span> {</span><br><span class="line"> <span class="keyword">switch</span> (lhs, rhs) {</span><br><span class="line"> <span class="keyword">case</span> <span class="keyword">let</span> (l?, r?):</span><br><span class="line"> <span class="keyword">return</span> <span class="type">ObjectIdentifier</span>(l) == <span class="type">ObjectIdentifier</span>(r)</span><br><span class="line"> <span class="keyword">case</span> (<span class="literal">nil</span>, <span class="literal">nil</span>):</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>从以上可以看出,<code>==</code>只是由实现好的静态函数决定,而<code>===</code>则是可以判断两个对象是否完全相等,这有点像判断两个指针相等一样,同样,我们要注意,如果两个可选对象都是nil,则也是<code>===</code>的;</p><ol start="3"><li>搞清楚两个问题</li></ol><ul><li><p>UTC 与 GMT<br>UTC(Coordinated Universal Time)标准时间参照,协调时间时,世界标准时间;<br>GMT(Greenwich Mean Time)时区,即格林尼治时间,位于本初子午线的标界处时间,世界计算时间和经度的起点,GMT是个时区,等同于世界时,所以GMT = UTC + 0,我们国家所在时间均以北京时间计算,北京位于东八区,所以时区为GMT + 8;</p></li><li><p>Locale<br>网上找了一圈,最后还是swift源码文档里给出的解释最靠谱:<code>Locale</code>封装了有关语言,文化和技术规范和标准的信息。由语言环境封装的信息示例包括,用于数字中小数点分隔符的符号以及格式化日期的方式。区域设置通常用于根据用户的习俗和偏好提供,格式化和解释信息。它们经常与格式化程序一起使用。虽然可以使用很多语言环境,但通常使用与当前用户关联的语言环境。<br>语言环境跟系统的环境设置有关,会涉及到操作系统语言环境设置,个人理解就是一个国际化的东西。<br>区域设置中的概念 LANGID & LCID:<br><img src="https://upload-images.jianshu.io/upload_images/1429775-04ff650284a51b6c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="LANGID & LCID"></p></li></ul>]]></content>
<summary type="html">
<p>我想你一定是在开玩笑。<br>源码怎么看,打开看呗!说这话的时候请收下我的轻蔑,哈哈。不过就这个问题我今天在知乎搜索了一通。不要问我为什么在知乎搜索,鬼知道知乎什么都有。<br>那么,请收下我的提问:<br>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="swift" scheme="http://charlesblog.site/tags/swift/"/>
<category term="UTC" scheme="http://charlesblog.site/tags/UTC/"/>
</entry>
<entry>
<title>本行三件事:猎龙 训龙 调教龙</title>
<link href="http://charlesblog.site/2018/04/27/%E6%9C%AC%E8%A1%8C%E4%B8%89%E4%BB%B6%E4%BA%8B%EF%BC%9A%E7%8C%8E%E9%BE%99%20%E8%AE%AD%E9%BE%99%20%E8%B0%83%E6%95%99%E9%BE%99/"/>
<id>http://charlesblog.site/2018/04/27/本行三件事:猎龙 训龙 调教龙/</id>
<published>2018-04-27T12:45:00.000Z</published>
<updated>2018-05-07T02:17:42.737Z</updated>
<content type="html"><![CDATA[<p>大家好,我是花木兰。<br><a id="more"></a></p><h2 id="第一件"><a href="#第一件" class="headerlink" title="第一件"></a>第一件</h2><p>今天在<strong>Nothing</strong>项目中添加了一个小的功能,就是按压屏幕出现一个有弹出效果的<em>Label</em>,涉及到的点;</p><ol><li>thereis</li></ol><ul><li>touches</li></ul><p>我们知道,UIResponder处理函数,根据不同的触摸状态会调用不同的函数,以下:<br><figure class="highlight erlang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">-<span class="params">(void)</span>touchesBegan:<span class="params">(NSSet *)</span>touches withEvent:<span class="params">(UIEvent *)</span>event;</span><br><span class="line"></span><br><span class="line">-<span class="params">(void)</span>touchesMoved:<span class="params">(NSSet *)</span>touches withEvent:<span class="params">(UIEvent *)</span>event;</span><br><span class="line"></span><br><span class="line">-<span class="params">(void)</span>touchesEnded:<span class="params">(NSSet *)</span>touches withEvent:<span class="params">(UIEvent *)</span>event;</span><br><span class="line"></span><br><span class="line">-<span class="params">(void)</span>touchesCancelled:<span class="params">(NSSet *)</span>touches withEvent:<span class="params">(UIEvent *)</span>event;</span><br></pre></td></tr></table></figure></p><p>注意第四个取消函数,调用时机是触摸被取消,一定要注意是被取消,自己主动点击然后结束这不叫取消,举个例子如在触摸过程中被来电打断,这种情况才算;<br>回调中可以通过<em>UITouch</em>来操作点击次数和手指数,<em>UIEvent</em>可以操作屏幕点信息,这样就把手指与屏幕的交互处理完成。</p><ul><li>transform<br>这里出现了一个现象,原代码如下:<figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//进入时的设置</span></span><br><span class="line"> <span class="comment">//向x y轴方向平移 0 0</span></span><br><span class="line"> self.transform = CGAffineTransform(<span class="string">translationX:</span> <span class="number">0</span>, <span class="string">y:</span> <span class="number">0</span>) <span class="comment">//(1)</span></span><br><span class="line"> self.transform = CGAffineTransform(<span class="string">rotationAngle:</span> <span class="number">0</span>) <span class="comment">// (2)</span></span><br><span class="line"> </span><br><span class="line"> self.transform = CGAffineTransform(<span class="string">scaleX:</span> <span class="number">0.1</span>, <span class="string">y:</span> <span class="number">0.1</span>) <span class="comment">//(3)</span></span><br><span class="line"> <span class="comment">//transform scale 改变中间不能添加其他变换</span></span><br><span class="line"> <span class="comment">//动画播放</span></span><br><span class="line"> UIView.animate(<span class="string">withDuration:</span> <span class="number">0.5</span>, <span class="string">delay:</span> <span class="number">0</span>, <span class="string">options:</span> .curveEaseOut, <span class="string">animations:</span> {</span><br><span class="line"> self.transform = CGAffineTransform(<span class="string">scaleX:</span> <span class="number">1</span>, <span class="string">y:</span> <span class="number">1</span>)</span><br><span class="line"> }, <span class="string">completion:</span> nil) <span class="comment">//(4)</span></span><br></pre></td></tr></table></figure></li></ul><p>如上代码<em>(2)</em>如果放在<em>(3)</em>和<em>(4)</em>的中间,则动画会不执行,直接形成动画后的结果,天知道这其中发生了什么,怕是动画函数做了某些优化,如果你知道,还请赐教。</p><ul><li>Another Problem<figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">UIView.animate(<span class="string">withDuration:</span> <span class="number">1</span>, <span class="string">delay:</span> <span class="number">0</span>, </span><br><span class="line"><span class="string">usingSpringWithDamping:</span> <span class="number">0.5</span>, </span><br><span class="line"><span class="string">initialSpringVelocity:</span> <span class="number">0.5</span>, <span class="string">options:</span> .curveEaseIn, <span class="string">animations:</span> {</span><br><span class="line"> self.transform = CGAffineTransform(<span class="string">scaleX:</span> <span class="number">1</span>, <span class="string">y:</span> <span class="number">1</span>)</span><br><span class="line">}, <span class="string">completion:</span> nil)</span><br><span class="line"><span class="comment">// 抗阻尼 以及 弹簧 的问题</span></span><br><span class="line"><span class="comment">// 涉及到了一些物理知识,不细究</span></span><br><span class="line"><span class="comment">// 只是贴出这个api 注意用法</span></span><br></pre></td></tr></table></figure></li></ul><ol start="2"><li>仿射变换</li></ol><p><a href="http://www.fuzihao.org/blog/2014/10/23/%E4%BB%BF%E5%B0%84%E7%A9%BA%E9%97%B4%E4%B8%8E%E4%BB%BF%E5%B0%84%E5%8F%98%E6%8D%A2/" target="_blank" rel="noopener">仿射空间和仿射变换</a><br>关于仿射变换的先看这篇文章了解一下吧,它是计算机图形学中一个很重要的概念,简单的理解就是线性变换加上平移变换,当然看到这里你得先知道什么是线性变换和平移变换,好了,这个概念先不多说了。</p><ol start="3"><li>currying function</li></ol><p>经过了一系列的实验,最终得出了一个函数链的方案,虽然跟柯里化没有什么关系,代码如下,细细品味一下:<br><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">func</span> <span class="title">maybe</span><span class="params">(noDate: NODate, <span class="number">_</span> some: <span class="params">()</span></span></span> -> ()) -> <span class="type">ThereIs</span> {</span><br><span class="line"> <span class="keyword">switch</span> noDate {</span><br><span class="line"> <span class="keyword">case</span> <span class="keyword">let</span> .<span class="type">April</span>(date):</span><br><span class="line"> <span class="keyword">let</span> myDate = date.toDate()</span><br><span class="line"> <span class="keyword">let</span> currentDate = <span class="type">Date</span>()</span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">let</span> myDate = myDate {</span><br><span class="line"> <span class="keyword">if</span> myDate.compare(currentDate) == .orderedSame {</span><br><span class="line"> some()</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">self</span></span><br><span class="line"> }</span><br></pre></td></tr></table></figure></p><p>其实也没有多么深奥,只是函数在调用外部传进的闭包后又返回了自身,然而,就是一个这样简单的设计,在调用时你会发现是多么的便利;<br><figure class="highlight maxima"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="symbol">_</span> = thereis?.<span class="built_in">maybe</span>(noDate: dates[<span class="number">0</span>]) {</span><br><span class="line"> self.noLabel.appear()</span><br><span class="line"> }</span><br><span class="line"> .<span class="built_in">maybe</span>(noDate: dates[<span class="number">1</span>]) {</span><br><span class="line"> </span><br><span class="line"> }</span><br></pre></td></tr></table></figure></p><p>上图中的<em>maybe</em>函数可以无限调用,这样根据传进来的参数可以实现一个小功能,如果将本方法的类似方法分散在不同的函数中调用,那么我们可以用传进不同参数来区分调用的时机,这样可以将某一次的逻辑调用统一在一个地方处理,说的有点绕,用一张图来理一下思路:<br><img src="https://upload-images.jianshu.io/upload_images/1429775-e58a9faeb3c885d6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="maybe函数思维导图"></p><h2 id="第二件"><a href="#第二件" class="headerlink" title="第二件"></a>第二件</h2><p>此时我面前有一个作业,叫做文献综述,今天跟老铁聊天中发现自己在面对困难问题时拖延的问题。朋友说当你有一大堆的事情不知道做哪件时,挑最难的那件事情做。<br>于是把每天最棘手的问题做为首要,比方说难做的作业,比方说写一篇文章。<br><img src="http://upload-images.jianshu.io/upload_images/1429775-1aea7d4c63680f89.jpg" alt="轻课听力"><br>上图是昨晚在轻课群的口语练习,留作复习用。</p><h2 id="第三件"><a href="#第三件" class="headerlink" title="第三件"></a>第三件</h2><p>已经很久没有写日志了,这么些年断断续续的,从来没把它当作一个习惯来做。在github上看到一个学习库,有所启发,想来该培养一个习惯来让自己保持一个学习的状态。完成的并不一定要完美,完成就好,记录下心情,记录下问题,记录下昨天那个“愚蠢”的自己。</p>]]></content>
<summary type="html">
<p>大家好,我是花木兰。<br>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="iOS" scheme="http://charlesblog.site/tags/iOS/"/>
<category term="paradigm" scheme="http://charlesblog.site/tags/paradigm/"/>
</entry>
<entry>
<title>朴素贝叶斯使用Python进行文本分类</title>
<link href="http://charlesblog.site/2018/04/17/%E6%9C%B4%E7%B4%A0%E8%B4%9D%E5%8F%B6%E6%96%AF%E4%BD%BF%E7%94%A8Python%E8%BF%9B%E8%A1%8C%E6%96%87%E6%9C%AC%E5%88%86%E7%B1%BB/"/>
<id>http://charlesblog.site/2018/04/17/朴素贝叶斯使用Python进行文本分类/</id>
<published>2018-04-17T15:08:00.000Z</published>
<updated>2018-05-07T02:17:42.737Z</updated>
<content type="html"><![CDATA[<p>这是我第一篇关于机器学习的文章。<br><a id="more"></a></p><ol><li>从文本中创建词向量bayes.py</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!usr/bin/python</span></span><br><span class="line"><span class="comment">#-*-encoding:utf-8-*-</span></span><br><span class="line"></span><br><span class="line"><span class="string">'''</span></span><br><span class="line"><span class="string">该函数返回实验样本,该样本被切分成词条集合;</span></span><br><span class="line"><span class="string">第二个变量返回类别,该类别由人工标注,用于训练程序以便自动检查侮辱性留言;</span></span><br><span class="line"><span class="string">'''</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">loadDataSet</span><span class="params">()</span>:</span></span><br><span class="line">postingList = [</span><br><span class="line">[<span class="string">'my'</span>,<span class="string">'dog'</span>,<span class="string">'has'</span>,<span class="string">'flea'</span>,<span class="string">'problems'</span>,<span class="string">'help'</span>,<span class="string">'please'</span>],</span><br><span class="line">[<span class="string">'maybe'</span>,<span class="string">'not'</span>,<span class="string">'take'</span>,<span class="string">'him'</span>,<span class="string">'to'</span>,<span class="string">'dog'</span>,<span class="string">'park'</span>,<span class="string">'stupid'</span>],</span><br><span class="line">[<span class="string">'my'</span>,<span class="string">'dalmation'</span>,<span class="string">'is'</span>,<span class="string">'so'</span>,<span class="string">'cute'</span>,<span class="string">'I'</span>,<span class="string">'love'</span>,<span class="string">'him'</span>],</span><br><span class="line">[<span class="string">'stop'</span>,<span class="string">'posting'</span>,<span class="string">'stupid'</span>,<span class="string">'worthless'</span>,<span class="string">'garbage'</span>],</span><br><span class="line">[<span class="string">'mr'</span>,<span class="string">'licks'</span>,<span class="string">'ate'</span>,<span class="string">'my'</span>,<span class="string">'steak'</span>,<span class="string">'how'</span>,<span class="string">'to'</span>,<span class="string">'stop'</span>,<span class="string">'him'</span>],</span><br><span class="line">[<span class="string">'quit'</span>,<span class="string">'buying'</span>,<span class="string">'worthless'</span>,<span class="string">'dog'</span>,<span class="string">'food'</span>,<span class="string">'stupid'</span>]</span><br><span class="line">]</span><br><span class="line">classVec = [<span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">1</span>] <span class="comment"># 1代表侮辱性文字 0代表正常</span></span><br><span class="line"><span class="keyword">return</span> postingList, classVec</span><br><span class="line"></span><br><span class="line"><span class="string">'''</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">'''</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">createVocabList</span><span class="params">(dataSet)</span>:</span></span><br><span class="line">vocabSet = set([])<span class="comment">#创建一个空集</span></span><br><span class="line"><span class="keyword">for</span> document <span class="keyword">in</span> dataSet:</span><br><span class="line">vocabSet = vocabSet | set(document) <span class="comment">#创建两集合并集</span></span><br><span class="line"><span class="keyword">return</span> list(vocabSet)</span><br><span class="line"></span><br><span class="line"><span class="string">'''</span></span><br><span class="line"><span class="string">该函数输入参数为词汇表及某个文档,输出的是文档向量,向量每一元素为1or0,分别表示词汇表中的单词在输入文档中是否出现</span></span><br><span class="line"><span class="string">'''</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">setOfWords2Vec</span><span class="params">(vocabList, inputSet)</span>:</span></span><br><span class="line">returnVec = [<span class="number">0</span>] * len(vocabList)</span><br><span class="line"><span class="keyword">for</span> word <span class="keyword">in</span> inputSet:</span><br><span class="line"><span class="keyword">if</span> word <span class="keyword">in</span> vocabList:</span><br><span class="line">returnVec[vocabList.index(word)] = <span class="number">1</span></span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">print(<span class="string">"the word: %s is not in my Vocabulary!"</span> % word)</span><br><span class="line"><span class="keyword">return</span> returnVec</span><br></pre></td></tr></table></figure><p><img src="http://static.zybuluo.com/usiege/08jgn0fh17i3tesytmd39qsl/image_1cb7dhd105761rg11lkq1mgjpt19.png" alt="image_1cb7dhd105761rg11lkq1mgjpt19.png-132.9kB"></p><ol start="2"><li>朴素贝叶斯训练函数</li></ol><figure class="highlight python"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">#朴素贝叶斯训练函数</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">trainNB0</span><span class="params">(trainMatrix, trainCategory)</span>:</span></span><br><span class="line">numTrainDocs = len(trainMatrix)</span><br><span class="line">numWords = len(trainMatrix[<span class="number">0</span>])</span><br><span class="line"></span><br><span class="line"><span class="comment">#</span></span><br><span class="line">pAbusive = sum(trainCategory)/float(numTrainDocs) </span><br><span class="line"></span><br><span class="line"><span class="comment">#某词出现次数</span></span><br><span class="line">p0Num = zeros(numWords)</span><br><span class="line">p1Num = zeros(numWords)</span><br><span class="line"><span class="comment">#在所有的文档中,出现某词的文档的总词数</span></span><br><span class="line">p0Denom = <span class="number">0.0</span></span><br><span class="line">p1Denom = <span class="number">0.0</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> range(numTrainDocs):</span><br><span class="line"><span class="keyword">if</span> trainCategory[i] == <span class="number">1</span>:</span><br><span class="line">p1Num += trainMatrix[i]</span><br><span class="line">p1Denom += sum(trainMatrix[i])</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">p0Num += trainMatrix[i]</span><br><span class="line">p0Denom += sum(trainMatrix[i])</span><br><span class="line"></span><br><span class="line">p1Vect = p1Num/p1Denom</span><br><span class="line">p0Vect = p0Num/p0Denom</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> p0Vect, p1Vect, pAbusive</span><br></pre></td></tr></table></figure><p><img src="http://static.zybuluo.com/usiege/41wgod8054yss08dj5zcae5d/image_1cb7gr8l6tli1gq8515ev19i013.png" alt="image_1cb7gr8l6tli1gq8515ev19i013.png-368.4kB"></p><p><img src="http://static.zybuluo.com/usiege/vw73jzr2d42s7l5us6duu8d8/image_1cb7gs04bmv319kp11841cvq73i1g.png" alt="image_1cb7gs04bmv319kp11841cvq73i1g.png-125.3kB"></p><ol start="3"><li>修改分类器</li></ol><ul><li>Problem1:计算多个概率的乘积以获得文档属于某个类别概率,如果其中有一个概率值为0,那最后乘积也为0;为降低这种影响,可以将所有词出现初始化为1,并将分母初始化为2</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">p0Num = ones(numWords); </span><br><span class="line">p1Num = ones(numWords)</span><br><span class="line">p0Denom = <span class="number">2.0</span>;</span><br><span class="line">p1Denom = <span class="number">2.0</span></span><br></pre></td></tr></table></figure><ul><li>Problem2: 下溢出,太多很小的数相乘会造成下溢出,解决办法是取自然对数,把乘法转换成加法,通过求对数避免下溢出或者浮点数舍入导致错误</li></ul><figure class="highlight python"><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">p1Vect = log(p1Num/p1Denom)</span><br><span class="line">p0Vect = log(p0Num/p0Denom)</span><br></pre></td></tr></table></figure><ol start="4"><li>分类器编写</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#构建朴素贝叶斯分类函数</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">classityNB</span><span class="params">(vec2Classify, p0Vec, p1Vec, pClass1)</span>:</span></span><br><span class="line">p1 = sum(vec2Classify * p1Vec) + log(pClass1)</span><br><span class="line">p0 = sum(vec2Classify * p0Vec) + log(<span class="number">1.0</span> - pClass1)</span><br><span class="line"><span class="keyword">if</span> p1 > p0: </span><br><span class="line"><span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"><span class="keyword">else</span>: </span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">testingNB</span><span class="params">()</span>:</span></span><br><span class="line">listOPosts, listClasses = loadDataSet()</span><br><span class="line">myVocabList = createVocabList(listOPosts)</span><br><span class="line">trainMat = []</span><br><span class="line"><span class="keyword">for</span> postinDoc <span class="keyword">in</span> listOPosts:</span><br><span class="line">trainMat.append(setOfWords2Vec(myVocabList, postinDoc))</span><br><span class="line">p0V, p1V, pAb = trainNB0(array(trainMat), array(listClasses))</span><br><span class="line"></span><br><span class="line">testEntry = [<span class="string">'love'</span>, <span class="string">'my'</span>, <span class="string">'dalmation'</span>]</span><br><span class="line">thisDoc = array(setOfWords2Vec(myVocabList, testEntry))</span><br><span class="line">print(testEntry, <span class="string">'classified as:'</span>, classityNB(thisDoc, p0V, p1V, pAb))</span><br><span class="line"></span><br><span class="line">testEntry = [<span class="string">'stupid'</span>, <span class="string">'garbage'</span>]</span><br><span class="line">thisDoc = array(setOfWords2Vec(myVocabList, testEntry))</span><br><span class="line">print(testEntry, <span class="string">'classified as:'</span>, classityNB(thisDoc, p0V, p1V, pAb))</span><br></pre></td></tr></table></figure><p>通过训练器分类得出结果:<br><img src="http://static.zybuluo.com/usiege/qfnldhvk83es60qqfapx4kn4/image_1cba21hoeuca2kt17n5bdu3e9p.png" alt="image_1cba21hoeuca2kt17n5bdu3e9p.png-38.4kB"></p><ol start="5"><li>文档词袋模型</li></ol><figure class="highlight python"><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="comment">#文档词袋模型</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">bagofWords2VecMN</span><span class="params">(vocabList, inputSet)</span>:</span></span><br><span class="line">returnVec = [<span class="number">0</span>] * len(vocabList)</span><br><span class="line"><span class="keyword">for</span> word <span class="keyword">in</span> inputSet:</span><br><span class="line"><span class="keyword">if</span> word <span class="keyword">in</span> vocabList:</span><br><span class="line">returnVec[vocabList.index(word)] += <span class="number">1</span></span><br><span class="line"><span class="keyword">return</span> returnVec</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p>这是我第一篇关于机器学习的文章。<br>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="Python" scheme="http://charlesblog.site/tags/Python/"/>
<category term="Mechine-Learning" scheme="http://charlesblog.site/tags/Mechine-Learning/"/>
</entry>
<entry>
<title>MGJRouter代码分析</title>
<link href="http://charlesblog.site/2018/01/07/MGJRouter%E4%BB%A3%E7%A0%81%E5%88%86%E6%9E%90/"/>
<id>http://charlesblog.site/2018/01/07/MGJRouter代码分析/</id>
<published>2018-01-07T09:21:00.000Z</published>
<updated>2018-05-07T02:17:42.730Z</updated>
<content type="html"><![CDATA[<p>今天来聊聊组件化,之前一直听说大厂在搞,什么淘宝架构,什么蘑菇街,既然谈到了架构的问题,那必属重中之重。接下来分析一下蘑菇街开源的代码,自己做个总结。<br><a id="more"></a></p><h3 id="引入"><a href="#引入" class="headerlink" title="引入"></a>引入</h3><p>类书本的文章个人感觉还是写不来的,再搬到自己写的东西这来也不合适,所以直接上一链接,通过链接文章大致可了解下它的前身后世,产生原因,以及整体宏观架构设计,而我接下来要做的是细化,以及转化,便于自己吸收<br>———> <a href="https://www.jianshu.com/p/67a6004f6930" target="_blank" rel="noopener">组件化架构漫谈</a></p><ol><li>话不多说,先看入口:</li></ol><p><img src="http://static.zybuluo.com/usiege/f0dci325k3jmmrh2l9uy51s4/image_1c25qj3m5ejq111g1v5lvkgjek9.png" alt="image_1c25qj3m5ejq111g1v5lvkgjek9.png-7.7kB"><br><figure class="highlight objectivec"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">@interface</span> <span class="title">MGJRouter</span> ()</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 保存了所有已注册的 URL</span></span><br><span class="line"><span class="comment"> * 结构类似 @{@"beauty": @{@":id": {@"_", [block copy]}}}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">@property</span> (<span class="keyword">nonatomic</span>) <span class="built_in">NSMutableDictionary</span> *routes;</span><br><span class="line"><span class="keyword">@end</span></span><br><span class="line"></span><br><span class="line">+ (<span class="keyword">instancetype</span>)sharedInstance</span><br><span class="line">{</span><br><span class="line"> <span class="keyword">static</span> MGJRouter *instance = <span class="literal">nil</span>;</span><br><span class="line"> <span class="keyword">static</span> <span class="built_in">dispatch_once_t</span> onceToken;</span><br><span class="line"> <span class="built_in">dispatch_once</span>(&onceToken, ^{</span><br><span class="line"> instance = [[<span class="keyword">self</span> alloc] init];</span><br><span class="line"> });</span><br><span class="line"> <span class="keyword">return</span> instance;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>很明显,蘑菇街架构(以下简称MGJ)通过该单例作管理,统一进行调配,而该单例仅有一个变量,就是<strong>routes</strong>,实际上它仅仅是管理了一个字典的结构,具体字典内有哪些内容,我们慢慢看;</p><ol start="2"><li>回调Block的定义</li></ol><figure class="highlight elm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * routerParameters 里内置的几个参数会用到上面定义的 string</span><br><span class="line"> */</span><br><span class="line">typedef void (^<span class="type">MGJRouterHandler</span>)(<span class="type">NSDictionary</span> *routerParameters);</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * 需要返回一个 object,配合 objectForURL: 使用</span><br><span class="line"> */</span><br><span class="line">typedef id (^<span class="type">MGJRouterObjectHandler</span>)(<span class="type">NSDictionary</span> *routerParameters);</span><br></pre></td></tr></table></figure><p>上面这两个block定义是MGJ注册URL的回调,一个带返回值,另一个不带,在这里我们说一下<strong>带返回值的block用法</strong>;如下举例 ——><br><img src="http://static.zybuluo.com/usiege/xn1r7ergmr6xr6msy2p5tyrh/WX20180107-134538@2x.png" alt="WX20180107-134538@2x.png-37.5kB"><br><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//声明</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="built_in">UIViewController</span> *(^ViewControllerHandler)();</span><br><span class="line"></span><br><span class="line"><span class="comment">//作参数</span></span><br><span class="line"><span class="class"><span class="keyword">@interface</span> <span class="title">DemoListViewController</span> : <span class="title">UIViewController</span></span></span><br><span class="line">+ (<span class="keyword">void</span>)registerWithTitle:(<span class="built_in">NSString</span> *)title handler:(ViewControllerHandler)handler;</span><br><span class="line"><span class="keyword">@end</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//定义</span></span><br><span class="line"><span class="class"><span class="keyword">@implementation</span> <span class="title">DemoListViewController</span></span></span><br><span class="line">+ (<span class="keyword">void</span>)registerWithTitle:(<span class="built_in">NSString</span> *)title handler:(ViewControllerHandler)handler</span><br><span class="line">{</span><br><span class="line"> <span class="built_in">UIViewController</span>* vc = handler()</span><br><span class="line">}</span><br><span class="line"><span class="keyword">@end</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//在别处调用</span></span><br><span class="line"><span class="class"><span class="keyword">@implementation</span> <span class="title">DemoDetailViewController</span></span></span><br><span class="line">[DemoListViewController registerWithTitle:<span class="string">@"基本使用"</span> handler:^<span class="built_in">UIViewController</span> *{</span><br><span class="line"> <span class="keyword">return</span> DemoDetailViewController();</span><br><span class="line">}];</span><br><span class="line"><span class="keyword">@end</span></span><br></pre></td></tr></table></figure></p><p>如上,我们把<code>ViewControllerHandler</code>的运行延迟到了实际调用的时刻,并且我们可以在这个handler的实现中带入很多信息;</p><ol start="3"><li>MGJ数据结构管理</li></ol><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">extern</span> <span class="built_in">NSString</span> *<span class="keyword">const</span> MGJRouterParameterURL;</span><br><span class="line"><span class="keyword">extern</span> <span class="built_in">NSString</span> *<span class="keyword">const</span> MGJRouterParameterCompletion;</span><br><span class="line"><span class="keyword">extern</span> <span class="built_in">NSString</span> *<span class="keyword">const</span> MGJRouterParameterUserInfo;</span><br><span class="line"><span class="comment">//*************************************************</span></span><br><span class="line"><span class="keyword">static</span> <span class="built_in">NSString</span> * <span class="keyword">const</span> MGJ_ROUTER_WILDCARD_CHARACTER = <span class="string">@"~"</span>; <span class="comment">//这是一个占位符</span></span><br><span class="line"><span class="keyword">static</span> <span class="built_in">NSString</span> *specialCharacters = <span class="string">@"/?&."</span>;</span><br><span class="line"></span><br><span class="line"><span class="built_in">NSString</span> *<span class="keyword">const</span> MGJRouterParameterURL = <span class="string">@"MGJRouterParameterURL"</span>;</span><br><span class="line"><span class="built_in">NSString</span> *<span class="keyword">const</span> MGJRouterParameterCompletion = <span class="string">@"MGJRouterParameterCompletion"</span>;</span><br><span class="line"><span class="built_in">NSString</span> *<span class="keyword">const</span> MGJRouterParameterUserInfo = <span class="string">@"MGJRouterParameterUserInfo"</span>;</span><br></pre></td></tr></table></figure><p>从这里我们可以看出,MGJ的路由管理,实际上是一个解析url以及对应的管理,我们举几个URL来看一下:<br><figure class="highlight mel"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">@"mgj:<span class="comment">//"</span></span><br><span class="line">@"mgj:<span class="comment">//foo/bar/none/exists"</span></span><br><span class="line">@"mgj:<span class="comment">//foo/bar" </span></span><br><span class="line">@"mgj:<span class="comment">//category/家居"</span></span><br><span class="line">@"mgj:<span class="comment">//category/travel"</span></span><br><span class="line">@"mgj:<span class="comment">//search/:query"</span></span><br><span class="line">@"mgj:<span class="comment">//detail"</span></span><br><span class="line">@"mgj:<span class="comment">//search/:keyword"</span></span><br><span class="line">@"mgj:<span class="comment">//search_top_bar"</span></span><br></pre></td></tr></table></figure></p><p>通过上面的URL我们可以看出,路由的管理实际上就是url的解析过程,下面我们来具体看一下解析过程;</p><ol start="4"><li>URL解析</li></ol><ul><li>route url</li></ul><p><img src="http://static.zybuluo.com/usiege/wr5j4jwfcaov7yfmx3u82nyk/WX20180107-150437@2x.png" alt="WX20180107-150437@2x.png-59.1kB"><br><figure class="highlight groovy"><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></pre></td><td class="code"><pre><span class="line">- (NSArray*)<span class="string">pathComponentsFromURL:</span>(NSString*)URL</span><br><span class="line">{</span><br><span class="line"> NSMutableArray *pathComponents = [NSMutableArray array];</span><br><span class="line"> <span class="keyword">if</span> ([URL <span class="string">rangeOfString:</span>@<span class="string">"://"</span>].location != NSNotFound) {</span><br><span class="line"> NSArray *pathSegments = [URL <span class="string">componentsSeparatedByString:</span>@<span class="string">"://"</span>];</span><br><span class="line"> <span class="comment">// 如果 URL 包含协议,那么把协议作为第一个元素放进去</span></span><br><span class="line"> [pathComponents <span class="string">addObject:</span>pathSegments[<span class="number">0</span>]];</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 如果只有协议,那么放一个占位符</span></span><br><span class="line"> URL = pathSegments.lastObject;</span><br><span class="line"> <span class="keyword">if</span> (!URL.length) {</span><br><span class="line"> [pathComponents <span class="string">addObject:</span>MGJ_ROUTER_WILDCARD_CHARACTER];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (NSString *pathComponent <span class="keyword">in</span> [[NSURL <span class="string">URLWithString:</span>URL] pathComponents]) {</span><br><span class="line"> <span class="keyword">if</span> ([pathComponent <span class="string">isEqualToString:</span>@<span class="string">"/"</span>]) <span class="keyword">continue</span>;</span><br><span class="line"> <span class="keyword">if</span> ([[pathComponent <span class="string">substringToIndex:</span><span class="number">1</span>] <span class="string">isEqualToString:</span>@<span class="string">"?"</span>]) <span class="keyword">break</span>;</span><br><span class="line"> [pathComponents <span class="string">addObject:</span>pathComponent];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> [pathComponents copy];</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><ul><li><p>key-value<br><img src="http://static.zybuluo.com/usiege/j23e7t541u0wcoohza0ktqmb/WX20180107-151956@2x.png" alt="WX20180107-151956@2x.png-111.8kB"></p><figure class="highlight objectivec"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">- (<span class="built_in">NSMutableDictionary</span> *)addURLPattern:(<span class="built_in">NSString</span> *)URLPattern</span><br><span class="line">{</span><br><span class="line"> <span class="built_in">NSArray</span> *pathComponents = [<span class="keyword">self</span> pathComponentsFromURL:URLPattern];</span><br><span class="line"></span><br><span class="line"> <span class="built_in">NSMutableDictionary</span>* subRoutes = <span class="keyword">self</span>.routes;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">for</span> (<span class="built_in">NSString</span>* pathComponent <span class="keyword">in</span> pathComponents) {</span><br><span class="line"> <span class="keyword">if</span> (![subRoutes objectForKey:pathComponent]) {</span><br><span class="line"> subRoutes[pathComponent] = [[<span class="built_in">NSMutableDictionary</span> alloc] init];</span><br><span class="line"> }</span><br><span class="line"> subRoutes = subRoutes[pathComponent];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> subRoutes;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>核心url解析</p></li></ul><p><img src="http://static.zybuluo.com/usiege/cbn7v2xkwlfy3c19m322o7mg/WX20180107-160319@2x.png" alt="WX20180107-160319@2x.png-147.8kB"><br><figure class="highlight objectivec"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line">- (<span class="built_in">NSMutableDictionary</span> *)extractParametersFromURL:(<span class="built_in">NSString</span> *)url</span><br><span class="line">{</span><br><span class="line"> <span class="built_in">NSMutableDictionary</span>* parameters = [<span class="built_in">NSMutableDictionary</span> dictionary];</span><br><span class="line"> </span><br><span class="line"> parameters[MGJRouterParameterURL] = url;</span><br><span class="line"> </span><br><span class="line"> <span class="built_in">NSMutableDictionary</span>* subRoutes = <span class="keyword">self</span>.routes;</span><br><span class="line"> <span class="built_in">NSArray</span>* pathComponents = [<span class="keyword">self</span> pathComponentsFromURL:url];</span><br><span class="line"> </span><br><span class="line"> <span class="built_in">BOOL</span> found = <span class="literal">NO</span>;</span><br><span class="line"> <span class="comment">// borrowed from HHRouter(https://github.com/Huohua/HHRouter)</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="built_in">NSString</span>* pathComponent <span class="keyword">in</span> pathComponents) {</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 对 key 进行排序,这样可以把 ~ 放到最后</span></span><br><span class="line"> <span class="built_in">NSArray</span> *subRoutesKeys =[subRoutes.allKeys sortedArrayUsingComparator:^<span class="built_in">NSComparisonResult</span>(<span class="built_in">NSString</span> *obj1, <span class="built_in">NSString</span> *obj2) {</span><br><span class="line"> <span class="keyword">return</span> [obj1 compare:obj2];</span><br><span class="line"> }];</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">for</span> (<span class="built_in">NSString</span>* key <span class="keyword">in</span> subRoutesKeys) {</span><br><span class="line"> <span class="keyword">if</span> ([key isEqualToString:pathComponent] || [key isEqualToString:MGJ_ROUTER_WILDCARD_CHARACTER]) {</span><br><span class="line"> found = <span class="literal">YES</span>;</span><br><span class="line"> subRoutes = subRoutes[key];</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> ([key hasPrefix:<span class="string">@":"</span>]) {</span><br><span class="line"> found = <span class="literal">YES</span>;</span><br><span class="line"> subRoutes = subRoutes[key];</span><br><span class="line"> <span class="built_in">NSString</span> *newKey = [key substringFromIndex:<span class="number">1</span>];</span><br><span class="line"> <span class="built_in">NSString</span> *newPathComponent = pathComponent;</span><br><span class="line"> <span class="comment">// 再做一下特殊处理,比如 :id.html -> :id</span></span><br><span class="line"> <span class="keyword">if</span> ([<span class="keyword">self</span>.class checkIfContainsSpecialCharacter:key]) {</span><br><span class="line"> <span class="built_in">NSCharacterSet</span> *specialCharacterSet = [<span class="built_in">NSCharacterSet</span> characterSetWithCharactersInString:specialCharacters];</span><br><span class="line"> <span class="built_in">NSRange</span> range = [key rangeOfCharacterFromSet:specialCharacterSet];</span><br><span class="line"> <span class="keyword">if</span> (range.location != <span class="built_in">NSNotFound</span>) {</span><br><span class="line"> <span class="comment">// 把 pathComponent 后面的部分也去掉</span></span><br><span class="line"> newKey = [newKey substringToIndex:range.location - <span class="number">1</span>];</span><br><span class="line"> <span class="built_in">NSString</span> *suffixToStrip = [key substringFromIndex:range.location];</span><br><span class="line"> newPathComponent = [newPathComponent stringByReplacingOccurrencesOfString:suffixToStrip withString:<span class="string">@""</span>];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> parameters[newKey] = newPathComponent;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 如果没有找到该 pathComponent 对应的 handler,则以上一层的 handler 作为 fallback</span></span><br><span class="line"> <span class="keyword">if</span> (!found && !subRoutes[<span class="string">@"_"</span>]) {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">nil</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// Extract Params From Query.</span></span><br><span class="line"> <span class="built_in">NSArray</span><<span class="built_in">NSURLQueryItem</span> *> *queryItems = [[<span class="built_in">NSURLComponents</span> alloc] initWithURL:[[<span class="built_in">NSURL</span> alloc] initWithString:url] resolvingAgainstBaseURL:<span class="literal">false</span>].queryItems;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">for</span> (<span class="built_in">NSURLQueryItem</span> *item <span class="keyword">in</span> queryItems) {</span><br><span class="line"> parameters[item.name] = item.value;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (subRoutes[<span class="string">@"_"</span>]) {</span><br><span class="line"> parameters[<span class="string">@"block"</span>] = [subRoutes[<span class="string">@"_"</span>] <span class="keyword">copy</span>];</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> parameters;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><figure class="highlight gams"><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></pre></td><td class="code"><pre><span class="line">+ (void)openURL:(NSString *)URL withUserInfo:(NSDictionary *)userInfo completion:(void (^)(id result))completion</span><br><span class="line">{</span><br><span class="line"> URL = [URL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];</span><br><span class="line"> NSMutableDictionary *<span class="keyword">parameters</span> = [[self <span class="comment">sharedInstance] extractParametersFromURL:URL]</span>;</span><br><span class="line"> </span><br><span class="line"> [<span class="keyword">parameters</span> enumerateKeysAndObjectsUsingBlock:^(id <span class="comment">key, NSString *obj, BOOL *stop) {</span></span><br><span class="line"> if <span class="comment">([obj isKindOfClass:[NSString class]]) {</span></span><br><span class="line"> <span class="keyword">parameters</span>[key] = [obj <span class="comment">stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]</span>;</span><br><span class="line"> }</span><br><span class="line"> }];</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">parameters</span>) {</span><br><span class="line"> MGJRouterHandler <span class="comment">handler = parameters[@</span><span class="comment">"block"</span><span class="comment">]</span>;</span><br><span class="line"> <span class="keyword">if</span> (completion) {</span><br><span class="line"> <span class="keyword">parameters</span>[MGJRouterParameterCompletion] = completion;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (userInfo) {</span><br><span class="line"> <span class="keyword">parameters</span>[MGJRouterParameterUserInfo] = userInfo;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//所以注册路由时的回调是在这里才调用到的</span></span><br><span class="line"> <span class="comment">//也就是openURL响应了register的回调</span></span><br><span class="line"> <span class="keyword">if</span> (handler) {</span><br><span class="line"> [<span class="keyword">parameters</span> removeObjectForKey:@<span class="string">"block"</span>];</span><br><span class="line"> handler(<span class="keyword">parameters</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol start="5"><li>后续?</li></ol>]]></content>
<summary type="html">
<p>今天来聊聊组件化,之前一直听说大厂在搞,什么淘宝架构,什么蘑菇街,既然谈到了架构的问题,那必属重中之重。接下来分析一下蘑菇街开源的代码,自己做个总结。<br>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="iOS" scheme="http://charlesblog.site/tags/iOS/"/>
<category term="modularization" scheme="http://charlesblog.site/tags/modularization/"/>
</entry>
<entry>
<title>Swift Currying(柯里化)</title>
<link href="http://charlesblog.site/2018/01/06/Swift%20Currying%EF%BC%88%E6%9F%AF%E9%87%8C%E5%8C%96%EF%BC%89/"/>
<id>http://charlesblog.site/2018/01/06/Swift Currying(柯里化)/</id>
<published>2018-01-06T08:34:00.000Z</published>
<updated>2018-05-07T02:17:42.732Z</updated>
<content type="html"><![CDATA[<p>Currying<br><a id="more"></a></p><ol><li>函数式编程思想</li></ol><p>先举一个小例子:<br><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">addOne</span><span class="params">(<span class="built_in">count</span>: Int)</span></span> -> <span class="type">Int</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">count</span> + <span class="number">1</span></span><br><span class="line">}</span><br><span class="line"><span class="comment">//上面这个代码我们是返回一个加和,和是使参数增加1;</span></span><br><span class="line"><span class="comment">//一个更加灵活的方法,我们可以取消上面的硬编码1;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">add</span><span class="params">(<span class="built_in">count</span>: Int, addition: Int)</span></span> -> <span class="type">Int</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">count</span> + addition</span><br><span class="line">}</span><br><span class="line"><span class="comment">//然而这个函数还并不是那么友好,我们用另外一种方法实现看一下:</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">add</span><span class="params">(<span class="number">_</span> addition: Int)</span></span> -> (<span class="type">Int</span>) -> <span class="type">Int</span> {</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> <span class="built_in">count</span> <span class="keyword">in</span> </span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">count</span> + addition</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//调用一下以上方法,看看有什么区别:</span></span><br><span class="line"><span class="keyword">let</span> number = add(<span class="built_in">count</span>: <span class="number">10</span>, addition: <span class="number">2</span>) <span class="comment">//函数2</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> add2 = add(<span class="number">2</span>) <span class="comment">//函数3</span></span><br><span class="line"><span class="keyword">let</span> number = add2(<span class="number">10</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> number = add(<span class="number">2</span>)(<span class="number">10</span>) <span class="comment">//函数3调用连起来是</span></span><br><span class="line"><span class="comment">//是不是觉得这种调用方式很熟悉,有点类似于</span></span><br><span class="line"><span class="comment">//classname.property.subproperty,点语法链</span></span><br></pre></td></tr></table></figure></p><p>显然这种编程方式更加灵活,所展现的内容更加直观,可以减少函数写N多的参数;当然函数式编程有的可不只是这些,更多内容不在本篇所讨论之内;</p><p>基于上例我们来写一个方法:<br><figure class="highlight livescript"><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">func greaterThan<span class="function"><span class="params">(_ comparer: Int)</span> -></span> <span class="function"><span class="params">(Int)</span> -></span> Bool {</span><br><span class="line"> <span class="keyword">return</span> { $<span class="number">0</span> > comparer }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> compareResult = greaterThan(<span class="number">10</span>)(<span class="number">11</span>)</span><br></pre></td></tr></table></figure></p><p>很明显下面这个式子的调用直观的表达了参数10和参数11的大小;</p><ol start="2"><li>target-action例子</li></ol><p>我们来看国外网上的一个例子:<br><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">protocol</span> <span class="title">TargetAction</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">func</span> <span class="title">performAction</span><span class="params">()</span></span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">TargetActionWrapper</span><<span class="title">T</span>: <span class="title">AnyObject</span>>: <span class="title">TargetAction</span> </span>{</span><br><span class="line"> <span class="keyword">weak</span> <span class="keyword">var</span> target: <span class="type">T</span>?</span><br><span class="line"> <span class="keyword">let</span> action: (<span class="type">T</span>) -> () -> (<span class="type">Void</span>)</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">func</span> <span class="title">performAction</span><span class="params">()</span></span> -> (<span class="type">Void</span>) {</span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">let</span> t = target {</span><br><span class="line"> action(t)()</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="class"><span class="keyword">enum</span> <span class="title">ControlEvent</span> </span>{</span><br><span class="line"> <span class="keyword">case</span> <span class="type">TouchUpInside</span></span><br><span class="line"> <span class="keyword">case</span> <span class="type">ValueChanged</span></span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line">} </span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Control</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> actions = [<span class="type">ControlEvent</span>: <span class="type">TargetAction</span>]()</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">convenience</span> <span class="keyword">init</span><<span class="type">T</span>: <span class="type">AnyObject</span>>(<span class="number">_</span> target: <span class="type">T</span>, action: @escaping (<span class="type">T</span>) -> () -> (<span class="type">Void</span>), controlEvent: <span class="type">ControlEvent</span>) {</span><br><span class="line"> actions[controlEvent] = <span class="type">TargetActionWrapper</span>(</span><br><span class="line"> target: target, action: action)</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">func</span> <span class="title">setTarget</span><T: AnyObject><span class="params">(target: T, action: @escaping <span class="params">(T)</span></span></span> -> () -> (<span class="type">Void</span>), controlEvent: <span class="type">ControlEvent</span>) {</span><br><span class="line"> </span><br><span class="line"> actions[controlEvent] = <span class="type">TargetActionWrapper</span>(target: target, action: action)</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">func</span> <span class="title">removeTargetForControlEvent</span><span class="params">(controlEvent: ControlEvent)</span></span> {</span><br><span class="line"> actions[controlEvent] = <span class="literal">nil</span></span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">func</span> <span class="title">performActionForControlEvent</span><span class="params">(controlEvent: ControlEvent)</span></span> {</span><br><span class="line"> actions[controlEvent]?.performAction()</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//我们来使用一下我们的模板</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">viewDidLoad</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="type">Control</span>().setTarget(<span class="keyword">self</span>, action: <span class="type">ViewController</span>.tapAction, controlEvent: .touchUpInside)</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">tapAction</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"单击了"</span>)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//如果我们不是用实例方法调用而是自定义构造函数的话</span></span><br><span class="line"><span class="comment">//我们能看到更好的表现方式</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">viewDidLoad</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="type">Control</span>.<span class="keyword">init</span>(<span class="keyword">self</span>, action: <span class="type">ViewController</span>.tapAction controlEvent: .touchUpInside)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//当然这个便利构造函数的例子用在这里并不是很合逻辑,但是我们只是想展现一下柯里化的内容</span></span><br></pre></td></tr></table></figure></p>]]></content>
<summary type="html">
<p>Currying<br>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="swift" scheme="http://charlesblog.site/tags/swift/"/>
</entry>
<entry>
<title>Jenkins 构建之脚本篇</title>
<link href="http://charlesblog.site/2017/12/12/Jenkins%20%E6%9E%84%E5%BB%BA%E4%B9%8B%E8%84%9A%E6%9C%AC%E7%AF%87/"/>
<id>http://charlesblog.site/2017/12/12/Jenkins 构建之脚本篇/</id>
<published>2017-12-12T12:53:00.000Z</published>
<updated>2018-05-07T02:17:42.730Z</updated>
<content type="html"><![CDATA[<p>之前一直纠结Xcode 9之后用Jenkins导出.ipa文件失败,后经朋友指点终于成功,在此结出终级解决之法;<br><a id="more"></a></p><p>大致思路是这样的:Jenkins在网页中的配置大多会在之后进行整理,最终在终端生成shell脚本,然后每完成一项就会在构建结果中显示成功,如有一步错,则整个构建过程将会失败,所以这就解释了之前构建一直卡在了Achiver成功之后。</p><p>基于上面的思路,则弃用之前的Jenkins配置,取消Jenkins项目中构建过程,Xcode配置全部清空,使用脚本配置,以下我会具体贴出,并适当讲解:</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/bin/bash -l</span></span><br><span class="line"><span class="builtin-name">export</span> <span class="attribute">LANG</span>=en_US.UTF-8</span><br><span class="line"><span class="builtin-name">export</span> <span class="attribute">LANGUAGE</span>=en_US.UTF-8</span><br><span class="line"><span class="builtin-name">export</span> <span class="attribute">LC_ALL</span>=en_US.UTF-8</span><br><span class="line"></span><br><span class="line"><span class="comment">#以下PROJECT_NAME为项目工程名称</span></span><br><span class="line">pod install --verbose --no-repo-update</span><br><span class="line">open PROJECT_NAME.xcworkspace</span><br><span class="line"></span><br><span class="line"><span class="comment">#以下USER_NAME为用户名</span></span><br><span class="line"><span class="attribute">project_path</span>=<span class="string">"/Users/USER_NAME/.jenkins/workspace/PROJECT_NAME"</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#指定项目地址</span></span><br><span class="line"><span class="attribute">workspace_path</span>=<span class="string">"<span class="variable">$project_path</span>/PROJECT_NAME.xcworkspace"</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#取当前时间字符串添加到文件夹结尾</span></span><br><span class="line"><span class="attribute">now</span>=$(date +<span class="string">"%Y_%m_%d_%H_%M_%S"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">#指定项目的scheme名称</span></span><br><span class="line"><span class="attribute">scheme</span>=<span class="string">"PROJECT_NAME"</span></span><br><span class="line"><span class="comment">#指定要打包的配置名</span></span><br><span class="line"><span class="attribute">configuration</span>=<span class="string">"Release"</span></span><br><span class="line"><span class="comment">#指定打包所使用的输出方式,目前支持app-store, package, ad-hoc, enterprise, development, 和developer-id,即xcodebuild的method参数</span></span><br><span class="line"><span class="attribute">export_method</span>=<span class="string">'enterprise'</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">#指定输出路径</span></span><br><span class="line"><span class="attribute">output_path</span>=<span class="string">"<span class="variable">$project_path</span>/build/PROJECT_NAME{now}"</span></span><br><span class="line"><span class="comment">#指定输出归档文件地址</span></span><br><span class="line"><span class="attribute">archive_path</span>=<span class="string">"<span class="variable">$output_path</span>/PROJECT_NAME.xcarchive"</span></span><br><span class="line"><span class="comment">#指定输出ipa名称</span></span><br><span class="line"><span class="attribute">ipa_name</span>=<span class="string">"PROJECT_NAME{now}.ipa"</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#指定输出ipa地址</span></span><br><span class="line"><span class="attribute">ipa_path</span>=<span class="string">"<span class="variable">$output_path</span>/<span class="variable">${ipa_name}</span>"</span></span><br><span class="line"><span class="comment">#指定打包配置</span></span><br><span class="line"><span class="attribute">export_plist_path</span>=<span class="string">"<span class="variable">$project_path</span>/ExportOptions.plist"</span></span><br><span class="line"><span class="comment">#获取执行命令时的commit message</span></span><br><span class="line"><span class="comment">#commit_msg="$(cat $project_path/build_log.txt)"</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#输出设定的变量值</span></span><br><span class="line">echo <span class="string">"===workspace path: <span class="variable">${workspace_path}</span>==="</span></span><br><span class="line">echo <span class="string">"===archive path: <span class="variable">${archive_path}</span>==="</span></span><br><span class="line">echo <span class="string">"===ipa path: <span class="variable">${ipa_path}</span>==="</span></span><br><span class="line">echo <span class="string">"===export method: <span class="variable">${export_method}</span>==="</span></span><br><span class="line"><span class="comment">#echo "===commit msg: ${commit_msg}==="</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#先清空前一次build</span></span><br><span class="line">xcodebuild clean -workspace <span class="variable">${workspace_path}</span> -scheme <span class="variable">${scheme}</span> -configuration <span class="variable">${configuration}</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#归档</span></span><br><span class="line">xcodebuild archive -workspace <span class="variable">${workspace_path}</span> -scheme <span class="variable">${scheme}</span> -archivePath <span class="variable">${archive_path}</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#导出</span></span><br><span class="line">xcodebuild -exportArchive -archivePath <span class="variable">${archive_path}</span> -exportPath <span class="variable">${output_path}</span> -exportOptionsPlist <span class="variable">${export_plist_path}</span></span><br></pre></td></tr></table></figure><p>依此上秘法,会获得Xcode 9下构建成功之案例,.ipa文件也会导出,至于之后上传到平台上,请到各平台下自行找文档整理,不做赘述。</p><p>今天新年,祝大家新年快乐,2018,代码不出bug,新技术很快上手,妹子泡到手软,工资涨的飞快,人生乐的飞起!!!</p>]]></content>
<summary type="html">
<p>之前一直纠结Xcode 9之后用Jenkins导出.ipa文件失败,后经朋友指点终于成功,在此结出终级解决之法;<br>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="jenkins" scheme="http://charlesblog.site/tags/jenkins/"/>
</entry>
<entry>
<title>Jenkins 100次构建失败踩坑全录(二)</title>
<link href="http://charlesblog.site/2017/12/10/Jenkins%20100%E6%AC%A1%E6%9E%84%E5%BB%BA%E5%A4%B1%E8%B4%A5%E8%B8%A9%E5%9D%91%E5%85%A8%E5%BD%95%EF%BC%88%E4%BA%8C%EF%BC%89/"/>
<id>http://charlesblog.site/2017/12/10/Jenkins 100次构建失败踩坑全录(二)/</id>
<published>2017-12-10T12:53:00.000Z</published>
<updated>2018-05-07T02:17:42.729Z</updated>
<content type="html"><![CDATA[<p>接上篇,继续踩坑,下面到构建触发器环节:<br><a id="more"></a></p><ul><li><p>构建触发器<br><img src="http://static.zybuluo.com/usiege/it14w81rja3zme63xykjxy5o/image_1c0qnmug31v0hvkf1pp1kqf1bir9.png" alt="image_1c0qnmug31v0hvkf1pp1kqf1bir9.png-91.5kB"><br>能用到的发图所示,说明在下方,自行研究,需要注意的一点是图中的*号之间是有空格的;</p></li><li><p>构建环境<br>这里又有一个超时,与上面的无关,这个是构建过程中的,根据需要添加,下面那个选项是时间戳;<br><img src="http://static.zybuluo.com/usiege/pjeg3kt1s3cb0rxb2l1dfsfr/image_1c0qooi0dkg7ls9abefu71n77p.png" alt="image_1c0qooi0dkg7ls9abefu71n77p.png-38.6kB"></p></li></ul><p>接下来是Keychains和Mobile PP,必填项;<br><img src="http://static.zybuluo.com/usiege/cjtc66sg8991c5ulj3uib8dq/image_1c0qosdhm132q23k103kckp1dok16.png" alt="image_1c0qosdhm132q23k103kckp1dok16.png-8kB"></p><p>逐个击破:<br>Keychains部分<br><img src="http://static.zybuluo.com/usiege/li5lfp7spsd6c3bw435besbb/image_1c0qovfpn1n431vc7n8qonb8o51j.png" alt="image_1c0qovfpn1n431vc7n8qonb8o51j.png-83.2kB"><br>这个部分也是选择题,因为之前你已经上传了,但是这里会出现无法选择的bug,点保存刷新下页面就可以选了,Variables部分填如下:<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash">{KEYCHAIN_PATH} <span class="variable">${KEYCHAIN_PASSWORD}</span> <span class="variable">${CODE_SIGNING_IDENTITY}</span></span></span><br></pre></td></tr></table></figure></p><p>Mobile Provisioning Profiles部分<br><img src="http://static.zybuluo.com/usiege/1s0il4bxtsop1ame15pbq0ul/image_1c0qprhce18lu1vjb1pd1aakjv20.png" alt="image_1c0qprhce18lu1vjb1pd1aakjv20.png-47.6kB"><br>这个部分同上,请选择你确定的PP文件,一定要对应好:<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash">{PROVISIONING_PROFILE}</span></span><br></pre></td></tr></table></figure></p><ul><li>构建</li></ul><p>整个配置过程最重要的部分,大多数问题都出在这里,我这里目前到了Archive阶段,也就是说归档成功,然后归档结果可以用xcode进行ipa打包,具体打包还要设置一个shell脚本,网上好多,有的可以用有的不可以,所以打算研究下这个脚本,自己写一个再上传,之后会在博客中跟进,现在先继续把已完成的部分写下来;</p><p>首先是先要加一个结束后的脚本,这个脚本不做打包操作,只是设置一下环境,以及配置一下有pod依赖的情况,如下:<br><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/bin/bash -l</span></span><br><span class="line"><span class="builtin-name">export</span> <span class="attribute">LANG</span>=en_US.UTF-8</span><br><span class="line"><span class="builtin-name">export</span> <span class="attribute">LANGUAGE</span>=en_US.UTF-8</span><br><span class="line"><span class="builtin-name">export</span> <span class="attribute">LC_ALL</span>=en_US.UTF-8</span><br><span class="line"></span><br><span class="line">pod install --verbose --no-repo-update</span><br><span class="line">open LeWaiJiao.xcworkspace</span><br></pre></td></tr></table></figure></p><p><img src="http://static.zybuluo.com/usiege/rxby0iwous3ppc63wyn1c83y/image_1c0qqc2ubcfq5tvuui19m3oi89.png" alt="image_1c0qqc2ubcfq5tvuui19m3oi89.png-47.4kB"></p><p>下面的那个<strong>Pack application,build and sign</strong> .ipa项就是打ipa的功能,暂时没有搞通,后续会补上来,先跳过;</p><p><img src="http://static.zybuluo.com/usiege/eceobb4arpah1xacmv2lmxrr/image_1c0qqnucp1np81vaj3rs1l7p1otdm.png" alt="image_1c0qqnucp1np81vaj3rs1l7p1otdm.png-97.4kB"></p><p><strong>Code signing & OS X keychain options</strong></p><p>下面的bundleID是你要进行打包的bundleID,info.plist是workspace下的路径,注意一下下面的Development Team ID这个ID是你的钥匙串上的证书名称,后面括号里的那一串字符,由字母和数字组成的,需要你自己做对应,下面的照着抄就行了,password填你电脑用户的密码,不要填错了;</p><p><img src="http://static.zybuluo.com/usiege/xhxhseh11fwg4wnbt8gpj95y/image_1c0qr7dli1unv1s7s1vu2ugm1fuh13.png" alt="image_1c0qr7dli1unv1s7s1vu2ugm1fuh13.png-102.7kB"></p><h1 id="贴几个Error:"><a href="#贴几个Error:" class="headerlink" title="贴几个Error:"></a>贴几个Error:</h1><figure class="highlight vhdl"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Code Signing <span class="literal">Error</span>: Code signing <span class="keyword">is</span> required <span class="keyword">for</span> product <span class="keyword">type</span> <span class="symbol">'Application</span>' <span class="keyword">in</span> SDK <span class="symbol">'iOS</span> <span class="number">11.1</span>'</span><br></pre></td></tr></table></figure><p>需要你在xcode中设置,然后上传到你们的Git服务器再构建:<br><img src="http://static.zybuluo.com/usiege/r85b8hxub85tfinbuzue1svp/image_1c0qs83ul1baipc04otg331geb1g.png" alt="image_1c0qs83ul1baipc04otg331geb1g.png-35.4kB"></p><figure class="highlight applescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">No <span class="keyword">global</span> development team <span class="keyword">or</span> <span class="keyword">local</span> team ID was configured.</span><br></pre></td></tr></table></figure><p>就是之前说的<strong>Development Team ID</strong>部分,填了就解决了;<br><a href="http://www.jianshu.com/p/8b2fc2da0466" target="_blank" rel="noopener">http://www.jianshu.com/p/8b2fc2da0466</a></p><figure class="highlight applescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xcodebuild: <span class="keyword">error</span>: The flag -scheme <span class="keyword">is</span> required when specifying -archivePath <span class="keyword">but</span> <span class="keyword">not</span> -exportArchive.</span><br></pre></td></tr></table></figure><p>这个问题也是个大坑,找了好久,也是搜狗找到的:<br><a href="http://www.jianshu.com/p/8967e4e27e9b" target="_blank" rel="noopener">http://www.jianshu.com/p/8967e4e27e9b</a><br><a href="https://www.tuicool.com/articles/zQ73Q3Q" target="_blank" rel="noopener">https://www.tuicool.com/articles/zQ73Q3Q</a><br><a href="https://github.com/jenkinsci/clang-scanbuild-plugin/commit/b970f5280a9c1929e9cd9d3b4d2b76a7d6cbc0dc" target="_blank" rel="noopener">https://github.com/jenkinsci/clang-scanbuild-plugin/commit/b970f5280a9c1929e9cd9d3b4d2b76a7d6cbc0dc</a></p><p>解决方法最直接的就是指定scheme和xcode workspace file,分别填你xcode工程中的scheme和pod生成的xcworkspace的名字;<br><img src="http://static.zybuluo.com/usiege/tlotqzvjbjlqk2ms1u43w2yd/image_1c0r0aqt33tdthopme188a2kk1t.png" alt="image_1c0r0aqt33tdthopme188a2kk1t.png-87.3kB"></p><p>有些同学不知道scheme在什么地方,如下图所示:<br><img src="http://static.zybuluo.com/usiege/1y4937ijhbvifle7jfgjg3ac/image_1c0r0eai5f09qj47rs134c1upu2a.png" alt="image_1c0r0eai5f09qj47rs134c1upu2a.png-145.6kB"></p><p>如上,能保证构建可以成功在Archive过程完成,如遇其他问题,欢迎评论区讨论;<br>之后会再继续完成打包ipa以及上传平台,同时之前提过的SSH部分会持续跟近,因为SSH与本文所讨论的内容并不十分吻合,所以这里不作讨论。</p>]]></content>
<summary type="html">
<p>接上篇,继续踩坑,下面到构建触发器环节:<br>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="jenkins" scheme="http://charlesblog.site/tags/jenkins/"/>
</entry>
<entry>
<title>Jenkins 100次构建失败踩坑全录(一)</title>
<link href="http://charlesblog.site/2017/12/09/Jenkins%20100%E6%AC%A1%E6%9E%84%E5%BB%BA%E5%A4%B1%E8%B4%A5%E8%B8%A9%E5%9D%91%E5%85%A8%E5%BD%95%EF%BC%88%E4%B8%80%EF%BC%89/"/>
<id>http://charlesblog.site/2017/12/09/Jenkins 100次构建失败踩坑全录(一)/</id>
<published>2017-12-09T12:53:00.000Z</published>
<updated>2018-05-07T02:17:42.729Z</updated>
<content type="html"><![CDATA[<p>本文将以问题与解决方案的方式对Jenkins构建过程中的问题进行收录,后期会在评论中持续收集,如果有相同情况,请自行对照解决;<br><a id="more"></a></p><p>本文参考:<br>手把手教你利用Jenkins持续集成iOS项目<br><a href="http://www.jianshu.com/p/41ecb06ae95f" target="_blank" rel="noopener">http://www.jianshu.com/p/41ecb06ae95f</a><br>关于iOS-Jenkins进行持续集成项目部署<br><a href="http://www.jianshu.com/p/54c7daae6c94" target="_blank" rel="noopener">http://www.jianshu.com/p/54c7daae6c94</a><br>iOS持续集成:Jenkins篇<br><a href="http://www.jianshu.com/p/faf879b3d182" target="_blank" rel="noopener">http://www.jianshu.com/p/faf879b3d182</a></p><h2 id="关卡1-:"><a href="#关卡1-:" class="headerlink" title="关卡1 :"></a>关卡1 :</h2><p>安装Jenkins:首先你的电脑得有一个Java环境,接下来安装Jenkins。你可以直接去<a href="https://jenkins.io" target="_blank" rel="noopener">Jenkins入口</a>网站,查看安装方式;<br>当然你也可以使用以下方法:</p><ul><li><p>安装homebrew</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> ruby -e <span class="string">"<span class="variable">$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)</span>"</span></span></span><br></pre></td></tr></table></figure></li><li><p>安装jenkins</p><figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ <span class="keyword">brew </span><span class="keyword">install </span><span class="keyword">jenkins</span></span><br></pre></td></tr></table></figure></li></ul><p>安装成功后需要开启jenkins服务;</p><h2 id="关卡2-:"><a href="#关卡2-:" class="headerlink" title="关卡2 :"></a>关卡2 :</h2><p>开启Jenkins服务:确认jenkins已安装,在终端进入到jenkins安装目录下,会有一个叫做jenkins.war的文件,<br><figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ <span class="keyword">java </span>-<span class="keyword">jar </span><span class="keyword">jenkins.war</span></span><br></pre></td></tr></table></figure></p><p>或者在终端输入:<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> jenkins</span></span><br></pre></td></tr></table></figure></p><p>当出现:<br><img src="http://static.zybuluo.com/usiege/uowhxmph61xngu3l2t4hxamh/image_1c0ptnl2j13mh1mn2hmk18qf7usp.png" alt="image_1c0ptnl2j13mh1mn2hmk18qf7usp.png-188.1kB"></p><p>服务已经就位,可以开始进行配置了;</p><p>这里还有两个命令用于jenkins开启和停用(Mac上):<br><figure class="highlight stylus"><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">$ sudo launchctl load /Library/LaunchDaemons/org<span class="selector-class">.jenkins-ci</span><span class="selector-class">.plist</span></span><br><span class="line">$ sudo launchctl unload /Library/LaunchDaemons/org<span class="selector-class">.jenkins-ci</span><span class="selector-class">.plist</span></span><br></pre></td></tr></table></figure></p><p>如果是linux上也可以这样:<br><figure class="highlight shell"><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"><span class="meta">$</span><span class="bash"> sudo systemctl status jenkins.service</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> sudo systemctl start jenkins.service</span></span><br></pre></td></tr></table></figure></p><p>不过实际操作过程中,可能会出现停用失败的情况,我的做法是直接打开活动监视器,在里面搜java服务,强制关闭掉;这里需要注意,如果服务没有停止再进行jenkins开启是不成功的,提示会告诉你已经在用:</p><p><img src="http://static.zybuluo.com/usiege/s46xl40yzd7t5gijpwdippc9/image_1c0pu09in491qq31bqs25f1hbg26.png" alt="image_1c0pu09in491qq31bqs25f1hbg26.png-222.9kB"></p><p>如果你想查看是否jenkins在运行,使用命令查看:<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> ps aux | grep jenkins</span></span><br></pre></td></tr></table></figure></p><h2 id="关卡3-:"><a href="#关卡3-:" class="headerlink" title="关卡3 :"></a>关卡3 :</h2><p>安装并开启完成就可以在浏览器里输入<a href="localhost:8080" target="_blank" rel="noopener">localhost:8080</a>进行页面化配置了;<br>安装完成之后,Safari可能会自动打开,如果没有自动打开,打开浏览器,输入<a href="http://localhost:8080" target="_blank" rel="noopener">http://localhost:8080</a><br><img src="http://static.zybuluo.com/usiege/fn2f1wx006r3chny2t5u9atc/image_1c0pvjgjqfbg3i01c371uhc1ves2j.png" alt="image_1c0pvjgjqfbg3i01c371uhc1ves2j.png-27.6kB"></p><p>这个时候可能会报一个错误。如果出现了这面的问题。出现这个问题的原因就是Java环境有问题,重启Java环境即可。</p><p>这个时候如果你重启电脑会发现Jenkins给你新增了一个用户,名字就叫Jenkins,不过这个时候你不知道密码。你可能会去试密码,肯定是是不对的,因为初始密码很复杂。这个时候正确做法是打开<a href="http://localhost:8080" target="_blank" rel="noopener">http://localhost:8080</a> 会出现下图的重设初始密码的界面。</p><p><img src="http://static.zybuluo.com/usiege/sfnjgdq201o27xta3ttqllkr/image_1c0pvl71n5dulcc413164i1hcp30.png" alt="image_1c0pvl71n5dulcc413164i1hcp30.png-30.4kB"></p><p>按照提示,找到/Users/Shared/Jenkins/Home/ 这个目录下,这个目录虽然是共享目录,但是有权限的,非Jenkins用户/secrets/目录是没有读写权限的。</p><p><img src="http://static.zybuluo.com/usiege/ltc8z86hbmzy78857uo767zr/image_1c0pvm8al1tce1iled5voi216ac3d.png" alt="image_1c0pvm8al1tce1iled5voi216ac3d.png-200.2kB"></p><p>打开initialAdminPassword文件,复制出密码,就可以填到网页上去重置密码了。如下图</p><p><img src="http://static.zybuluo.com/usiege/ub5cnhcl82hyed8j8aqghlna/image_1c0pvp2p01fon1h2mmvjs6s1fuj3q.png" alt="image_1c0pvp2p01fon1h2mmvjs6s1fuj3q.png-99.6kB"></p><p>一路安装过来,输入用户名,密码,邮件这些,就算安装完成了。</p><p>还是继续登录localhost:8080</p><p>然而这一关还没有结束:<br>写blog的时候我把自己设置的帐号注销了,然而当时设置的密码却忘记了,怎么都想不起来,怎么办呢?<br>首先我想能不能用之前给的Jenkins帐户呢,经试错,未果;<br>接下来上百度查了几种方法,有的方法很复杂,不打算用,我们只用最简单粗暴的;只要之前的帐号信息没有丢失,又可以进入系统就OK了,于是:</p><p><img src="http://static.zybuluo.com/usiege/ihh8n31m9fb1r9gomahd7l6d/image_1c0q0bnonde9a9omqa1092a1747.png" alt="image_1c0q0bnonde9a9omqa1092a1747.png-85.9kB"></p><p>注意实际操作过程中发现不是<code>/User/Shared/Jenkins/Home</code>下的config.xml,也不是<code>/User/Shared/Jenkins/Home/users</code>下的config.xml,而是<strong>你自己用户目录</strong><code>~/.jenkins/</code>下的config.xml,具体原因可能是jenkins运行的工作空间是当前用户目录下的<code>.jenkins</code>,然后就是这样:</p><p><img src="http://static.zybuluo.com/usiege/rmn1oao4inl6rvryb8ne596c/image_1c0q277tu152r9mg1dhg1edq8jp5q.png" alt="image_1c0q277tu152r9mg1dhg1edq8jp5q.png-55.9kB"></p><p>经检验,无误,可进入,但是好像遗留了一个问题,就是这样进入的话就找不到管理用户的选项了;解决问题,勾选图中黄色圈,返回系统管理,出现管理用户(还是个隐藏道具);<br><img src="http://static.zybuluo.com/usiege/v5zxzwu4pex59s78odynkkd6/image_1c0q3ukis1vlhib71uij1729ohs67.png" alt="image_1c0q3ukis1vlhib71uij1729ohs67.png-33.1kB"></p><p><img src="http://static.zybuluo.com/usiege/bxyfaeid922e3lf7dvuz9mh8/image_1c0q419b0164pqfe25d9br1fpt74.png" alt="image_1c0q419b0164pqfe25d9br1fpt74.png-39.8kB"></p><p><img src="http://static.zybuluo.com/usiege/burf10v126vjx00u2ym0h2bn/image_1c0q42m3mvf41d8fjs21ptb1ae77h.png" alt="image_1c0q42m3mvf41d8fjs21ptb1ae77h.png-11.4kB"></p><p>搞的像是特工登录非授权帐户一样,不管怎么说,总算是攻破了,进入下一关;</p><h2 id="关卡-4:"><a href="#关卡-4:" class="headerlink" title="关卡 4:"></a>关卡 4:</h2><p>先不管工程构建里那一堆设置,我们先来搞一下证书Cer,钥匙Keychain,配置文件Provisioning Profiles的一些问题:<br>首先去系统管理 -> 管理插件 -> 可选插件,搜索并安装Keychains and Provisioning Profiles Management插件;<br>进入插件:<br><img src="http://static.zybuluo.com/usiege/kgy8eq7ug16g0o1o4eotp3bw/image_1c0qeblep1tcj4m319ap1bek783ah.png" alt="image_1c0qeblep1tcj4m319ap1bek783ah.png-31.1kB"></p><p>不要关键去填下面的空,我会告诉你这是一道有选项的题目;进入文件目录,<code>Command + shift + G</code>,写下这样的路径<code>~/资源库/Keychains</code>,</p><p><img src="http://static.zybuluo.com/usiege/ebpz8l8bnnvlrr6oi3a0423h/image_1c0qekdqp9v712rd1gefjdr1fdcbe.png" alt="image_1c0qekdqp9v712rd1gefjdr1fdcbe.png-62.2kB"></p><p>这里我们把login.keychain-db上传到Jenkins里,但是Upload并不能上传这样后缀的文件,所以需要你手动把login.keychain-db修改成login.keychain(复制后再修改,以防止其他地方会引用到带-db);上传完成后就会在下面出现你一些信息;然后打开你的钥匙串,这个知道在什么地方吧;</p><p><img src="http://static.zybuluo.com/usiege/w9l7f921rn6he0vx1vcqmu6a/image_1c0qet898q8m118mk2s6kj1cq5eb.png" alt="image_1c0qet898q8m118mk2s6kj1cq5eb.png-131kB"></p><p>点击打包所用到的证书,将红色框中的名称复制出来,添加到identities中;</p><p><img src="http://static.zybuluo.com/usiege/zc1wu103t1woz01fp07s80b7/image_1c0qf02rofnpc3r121c1nlb1mqteo.png" alt="image_1c0qf02rofnpc3r121c1nlb1mqteo.png-42.7kB"></p><p>如果有多个,则点击Add Code Signing Identity添加;</p><p>然后是PP文件,这些文件需要我们从系统PP文件夹下复制到Jenkins资源文件夹下,如下图两个路径:<br>这个是系统PP文件目录<br><img src="http://static.zybuluo.com/usiege/peonwampxc6wa9h3i2yuhfm5/image_1c0qkdte41j1rgq81k8v1bi19f4f5.png" alt="image_1c0qkdte41j1rgq81k8v1bi19f4f5.png-144.2kB"><br>这个是Jenkins PP文件目录<br><img src="http://static.zybuluo.com/usiege/v0firte6p13gwec9a133ixi1/image_1c0qkkk833p0nt18andthn9qfi.png" alt="image_1c0qkkk833p0nt18andthn9qfi.png-79.2kB"></p><p>Provisioning Profiles Directory Path 填写成,注意替换为自己的username:</p><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="regexp">/User/</span>{USERNAME}<span class="regexp">/Library/</span>MobileDevice<span class="regexp">/Provisioning Profiles</span></span><br></pre></td></tr></table></figure><p>接着去你苹果帐号里去找你对应打包所需要的PP文件,然后点upload上传到Jenkins环境里;<br>以上,证书部分解决;</p><h2 id="关卡-5"><a href="#关卡-5" class="headerlink" title="关卡 5"></a>关卡 5</h2><p>创建项目过程我们会对各个需要的项进行逐个描述:<br>点新建项目,输入项目名称,选择 构建一个自由风格的软件项目,然后确定,进入配置页面。<br><img src="http://static.zybuluo.com/usiege/1ytel52lwidafke7uv5rmgb0/image_1c0ql3ppk1bht1b5ms4hcui1jpjfv.png" alt="image_1c0ql3ppk1bht1b5ms4hcui1jpjfv.png-8.2kB"></p><ul><li>General<br>这个部分的内容都很浅显,没有什么可以说的,根据需要自行填充;这里说一下GitLab connection选项,因为我自己的工程是用gitlab管理的代码,所以需要在Jenkins里下一个Gitlab的插件,然后在里面进行帐号配置,可以采用帐号密码以及SSH的方式,具体这个部分会有一个SSH的坑,先不作分析,后面会讲到,我这里先用帐号密码的方式进行构建,经检验发现SSH方式非必要;</li></ul><p><strong>Credentials</strong>在这里配置:<br><img src="http://static.zybuluo.com/usiege/f6pv0rsip2oirn32m01agp1l/image_1c0qljaq610ljc02k6g1r821fs5gc.png" alt="image_1c0qljaq610ljc02k6g1r821fs5gc.png-78.2kB"></p><ul><li>源码管理<br>这里我选的Git,<strong>Repository URL</strong>填你工程的git地址,选用帐号密码的形式应该是以http或https开头的,<strong>Credentials</strong>填你在上一步中新建好的,<br><img src="http://static.zybuluo.com/usiege/bzufeuzktht55r97i2bsem18/image_1c0qlt20313duogl2g51hp11nqsgp.png" alt="image_1c0qlt20313duogl2g51hp11nqsgp.png-73kB"><br><strong>Branch Specifier (blank for ‘any’)</strong> 填你要进行构建的分支,我这里是<code>*/release</code>;</li></ul><p>这里我们PS一个隐藏BOSS:<br><figure class="highlight subunit"><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">returned status code 143 jenkins</span><br><span class="line"><span class="keyword">ERROR: </span>Error fetching remote repo ‘origin’</span><br></pre></td></tr></table></figure></p><p>这个报错是工程配置结束后进行构建后提示的,我当时搞这个发现远程代码明明是已经拉取到本地的,只是在拉取过程中会发生中断,本人在进行了将近50次试错后发现这个拉取到本地的代码率是变化的,先前以为是SSH帐号的问题,于是转头花了一天的时间搞了下SSH,后来SSH搞通后发现该问题仍然存在,后来终于在经历百度,谷歌,搜狗也用上的(不得不说有时候百度搜不出来的搜狗能搜到),发现了几篇有用的,后来解决,也算是不负辛苦,后面有踩坑的伙伴多注意,前车之鉴后事之师;</p><p><a href="http://blog.sina.com.cn/s/blog_72ef7bea0102vo9w.html" target="_blank" rel="noopener">http://blog.sina.com.cn/s/blog_72ef7bea0102vo9w.html</a><br><a href="https://issues.jenkins-ci.org/browse/JENKINS-20445" target="_blank" rel="noopener">https://issues.jenkins-ci.org/browse/JENKINS-20445</a><br><a href="https://stackoverflow.com/questions/35069079/jenkins-git-plugin-timeout-when-try-to-pull-repositoty-using-ssh" target="_blank" rel="noopener">https://stackoverflow.com/questions/35069079/jenkins-git-plugin-timeout-when-try-to-pull-repositoty-using-ssh</a></p><p>解决方案就在于这个<strong>Timeout</strong>,相信你看了这个单词就知道是怎么回事了:<br><img src="http://static.zybuluo.com/usiege/firl86lawiru1uvz1jhelb28/image_1c0qmnlafh2p1j571b4ettv1ncah6.png" alt="image_1c0qmnlafh2p1j571b4ettv1ncah6.png-74.3kB"></p><p>另顺便粘一个code 128的链接,是个与该问题相关的问题,因为这些问题关键字有的重复,所以搜出来的文章有时会误导,所以请仔细辨别:<br><figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">returned status code 128 jenkins</span><br><span class="line"><span class="keyword">ERROR: </span>Error cloning remote repo 'origin'</span><br><span class="line">stderr: Permission denied (publickey).</span><br></pre></td></tr></table></figure></p><p><a href="http://wantcoding.com/?p=293" target="_blank" rel="noopener">http://wantcoding.com/?p=293</a><br><a href="http://www.cnblogs.com/EasonJim/p/6266892.html" target="_blank" rel="noopener">这个链接是附送的,进去多看看你会有惊喜,还有QQ群哦</a></p>]]></content>
<summary type="html">
<p>本文将以问题与解决方案的方式对Jenkins构建过程中的问题进行收录,后期会在评论中持续收集,如果有相同情况,请自行对照解决;<br>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="jenkins" scheme="http://charlesblog.site/tags/jenkins/"/>
</entry>
<entry>
<title>记一次iOS上线提审</title>
<link href="http://charlesblog.site/2017/12/07/%E8%AE%B0%E4%B8%80%E6%AC%A1iOS%E4%B8%8A%E7%BA%BF%E6%8F%90%E5%AE%A1/"/>
<id>http://charlesblog.site/2017/12/07/记一次iOS上线提审/</id>
<published>2017-12-07T09:50:00.000Z</published>
<updated>2018-05-07T02:17:42.738Z</updated>
<content type="html"><![CDATA[<p>公司最近的一次App提交过程中遇到的一些问题,现贴在这里,有检索到本篇的朋友们可借鉴。</p><a id="more"></a><p>首先是上传到iTunes Connect构建版本,点击以下蓝色按钮,之后会有苹果为你的代码进行检查:</p><p><img src="http://static.zybuluo.com/usiege/n72bt0t4wwh45zw5c0kjcv01/image_1bu7k3nt22m3cmearq636qua9.png" alt="image_1bu7k3nt22m3cmearq636qua9.png-14.8kB"></p><p>本人在ios11上做了提交,发现问题进行分类:</p><ol><li>第一个是第三方库存在x86_64,i386的链接库,有以下问题:</li></ol><figure class="highlight subunit"><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">iTunes Store Operation Failed</span><br><span class="line"><span class="keyword">ERROR </span>ITMS<span class="string">-90087</span>: "Unsupported Architectures. The executable for LeWaiJiao.app/Frameworks/GCDWebServers.framework contains unsupported architectures '[x86_64, i386]'."</span><br></pre></td></tr></table></figure><p>PS:以下所有翻译来源于欧路词典,粘贴过来的,仅供参考;<br><figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">iTunes Store Operation Failed</span><br><span class="line"><span class="keyword">ERROR </span>ITMS<span class="string">-90209</span>: "Invalid Segment Alignment. The app binary at 'LeWaiJiao.app/Frameworks/GCDWebServers.framework/GCDWebServers' does not have proper segment alignment. Try rebuilding the app with the latest Xcode version."</span><br><span class="line">无效段对齐。应用程序二进制的“lewaijiao。应用程序/框架/ gcdwebservers。框架/ gcdwebservers”没有正确对齐。尝试用新的Xcode版本重建应用程序。</span><br></pre></td></tr></table></figure></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">iTunes Store Operation Failed</span><br><span class="line">ERROR ITMS-90125: "The binary is invalid. The encryption info in the LC_ENCRYPTION_INFO <span class="keyword">load</span> command <span class="keyword">is</span> either <span class="keyword">missing</span> <span class="keyword">or</span> invalid, <span class="keyword">or</span> the <span class="built_in">binary</span> <span class="keyword">is</span> already encrypted. This <span class="built_in">binary</span> does <span class="keyword">not</span> seem <span class="keyword">to</span> have been built <span class="keyword">with</span> Apple<span class="string">'s linker."</span></span><br><span class="line"><span class="string">“二进制无效。在lc_encryption_info负荷指令加密信息丢失或无效,或是已经加密的二进制。这个二进制文件似乎没有用苹果的链接器构建。”</span></span><br></pre></td></tr></table></figure><figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">iTunes Store Operation Failed</span><br><span class="line">WARNING ITMS-90080: "The executable 'Payload/LeWaiJiao.app/Frameworks/GCDWebServers.framework' is not a Position Independent Executable. Please ensure that your <span class="keyword">build</span> settings are configured <span class="keyword">to</span> <span class="keyword">create</span> PIE executables. <span class="keyword">For</span> more information refer <span class="keyword">to</span> Technical Q&A QA1788 - Building a <span class="built_in">Position</span> Independent Executable <span class="keyword">in</span> the iOS Developer Library.<span class="string">"</span></span><br><span class="line"><span class="string">“可执行的有效载荷/ lewaijiao。应用程序/框架/ gcdwebservers。框架”不是一个独立的可执行文件的位置。请确保您的构建设置配置为创建饼可执行文件。更多信息请参阅技术问答qa1788在iOS开发者库位置独立的可执行的建筑。”</span></span><br></pre></td></tr></table></figure><figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ERROR </span>ITMS<span class="string">-90362</span>: "Invalid Info.plist value. The value for the key 'MinimumOSVersion' in bundle ***.app/Frameworks/SDK.framework is invalid. The minimum value is 8.0"</span><br></pre></td></tr></table></figure><p>后面这个<strong>90362</strong>貌似是连带问题,定位的时候发现与最小版本无关,所以一同被解决了;</p><p>解决方法呢是在该工程里添加脚本处理这些被添加进来的第三方库,如下:<br><img src="http://static.zybuluo.com/usiege/mqh6ttzi6hsixpddv5nmcu03/image_1bu7kmq06140t1nmhkf11sfq1civm.png" alt="image_1bu7kmq06140t1nmhkf11sfq1civm.png-235.5kB"><br><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><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></pre></td><td class="code"><pre><span class="line">APP_PATH=<span class="string">"<span class="variable">${TARGET_BUILD_DIR}</span>/<span class="variable">${WRAPPER_NAME}</span>"</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># This script loops through the frameworks embedded in the application and</span></span><br><span class="line"><span class="comment"># removes unused architectures.</span></span><br><span class="line">find <span class="string">"<span class="variable">$APP_PATH</span>"</span> -name <span class="string">'*.framework'</span> -<span class="built_in">type</span> d | <span class="keyword">while</span> <span class="built_in">read</span> -r FRAMEWORK</span><br><span class="line"><span class="keyword">do</span></span><br><span class="line">FRAMEWORK_EXECUTABLE_NAME=$(defaults <span class="built_in">read</span> <span class="string">"<span class="variable">$FRAMEWORK</span>/Info.plist"</span> CFBundleExecutable)</span><br><span class="line">FRAMEWORK_EXECUTABLE_PATH=<span class="string">"<span class="variable">$FRAMEWORK</span>/<span class="variable">$FRAMEWORK_EXECUTABLE_NAME</span>"</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">"Executable is <span class="variable">$FRAMEWORK_EXECUTABLE_PATH</span>"</span></span><br><span class="line"></span><br><span class="line">EXTRACTED_ARCHS=()</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> ARCH <span class="keyword">in</span> <span class="variable">$ARCHS</span></span><br><span class="line"><span class="keyword">do</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">"Extracting <span class="variable">$ARCH</span> from <span class="variable">$FRAMEWORK_EXECUTABLE_NAME</span>"</span></span><br><span class="line">lipo -extract <span class="string">"<span class="variable">$ARCH</span>"</span> <span class="string">"<span class="variable">$FRAMEWORK_EXECUTABLE_PATH</span>"</span> -o <span class="string">"<span class="variable">$FRAMEWORK_EXECUTABLE_PATH</span>-<span class="variable">$ARCH</span>"</span></span><br><span class="line">EXTRACTED_ARCHS+=(<span class="string">"<span class="variable">$FRAMEWORK_EXECUTABLE_PATH</span>-<span class="variable">$ARCH</span>"</span>)</span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">"Merging extracted architectures: <span class="variable">${ARCHS}</span>"</span></span><br><span class="line">lipo -o <span class="string">"<span class="variable">$FRAMEWORK_EXECUTABLE_PATH</span>-merged"</span> -create <span class="string">"<span class="variable">${EXTRACTED_ARCHS[@]}</span>"</span></span><br><span class="line">rm <span class="string">"<span class="variable">${EXTRACTED_ARCHS[@]}</span>"</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">"Replacing original executable with thinned version"</span></span><br><span class="line">rm <span class="string">"<span class="variable">$FRAMEWORK_EXECUTABLE_PATH</span>"</span></span><br><span class="line">mv <span class="string">"<span class="variable">$FRAMEWORK_EXECUTABLE_PATH</span>-merged"</span> <span class="string">"<span class="variable">$FRAMEWORK_EXECUTABLE_PATH</span>"</span></span><br><span class="line"><span class="keyword">done</span></span><br></pre></td></tr></table></figure></p><p>以上代码来源于Google,解决方法经确认iOS11 + Xcode9.0有效;</p><ol start="2"><li>项目有icon不合规定的错误<figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">iTunes Store Operation Failed</span><br><span class="line"><span class="keyword">ERROR </span>ITMS<span class="string">-90717</span>: "Invalid App Store Icon. The App Store Icon in the asset catalog in 'LeWaiJiao.app' can't be transparent nor contain an alpha channel."</span><br><span class="line">无效应用程序商店图标。在资产目录中的lewaijiao App Store图标,应用程序不能透明也包含alpha通道。”</span><br></pre></td></tr></table></figure></li></ol><p>该错误原因是上传的icon不符合苹果规定,公司项目存在的问题是1.使用了圆角;2.有透明alpha通道;<br>解决方法自然容易了,找设计重新做,自己解决的话第二个可以DIY,如下:</p><p><img src="http://static.zybuluo.com/usiege/xtde6py269a5m4iusbumms4p/image_1bu7l6vhrvhm51b13pjvrlc0p13.png" alt="image_1bu7l6vhrvhm51b13pjvrlc0p13.png-100.4kB"></p><p>用系统预览打开icon图片,点掉Alpha的勾,再保存就可以了;<br><img src="http://static.zybuluo.com/usiege/yql5tndy4d612fhqfsi9n4l2/image_1bu7l8bt61p6v1mp11csi15ri1dmg1g.png" alt="image_1bu7l8bt61p6v1mp11csi15ri1dmg1g.png-128.6kB"></p><ol start="3"><li>提交上传结束后又出现了一个问题</li></ol><figure class="highlight stata"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">App</span> Installation failed, <span class="keyword">No</span> code signature found.</span><br></pre></td></tr></table></figure><p>真机无法运行了!这个问题纯属偶然,所以继续解决;打开终端,输入</p><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo chmod -R <span class="number">777</span> <span class="regexp">/Applications/</span>Xcode.app<span class="regexp">/Contents/</span>Developer<span class="regexp">/Platforms/i</span>PhoneOS.platform<span class="regexp">/Developer/</span>SDKs<span class="regexp">/iPhoneOS.sdk</span></span><br></pre></td></tr></table></figure><p>修改文件权限,然后修改字段属性,打开:</p><p><strong>/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/SDKSettings.plist</strong></p><p>,修改 <strong>CODE_SIGNING_REQUIRED</strong> 字段为 <strong>YES</strong> ,保存;</p>]]></content>
<summary type="html">
<p>公司最近的一次App提交过程中遇到的一些问题,现贴在这里,有检索到本篇的朋友们可借鉴。</p>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="iOS" scheme="http://charlesblog.site/tags/iOS/"/>
</entry>
<entry>
<title>Python-django安装</title>
<link href="http://charlesblog.site/2017/10/25/Python-django%E5%AE%89%E8%A3%85/"/>
<id>http://charlesblog.site/2017/10/25/Python-django安装/</id>
<published>2017-10-25T11:56:00.000Z</published>
<updated>2018-05-07T02:17:42.731Z</updated>
<content type="html"><![CDATA[<p>django<br><a id="more"></a></p><ol><li><p>发现错误<br><img src="http://static.zybuluo.com/usiege/tvcs5iet0ge1yypcquu2swdq/image_1bt9d9b27bv5glj1a0m15hr1ncn9.png" alt="image_1bt9d9b27bv5glj1a0m15hr1ncn9.png-258.7kB"><br>怀疑是pip版本的问题;</p></li><li><p>于是查了下更新pip的方法: </p></li></ol><p>查看pip版本<br><figure class="highlight applescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip -<span class="built_in">version</span></span><br></pre></td></tr></table></figure></p><p>升级方法<br><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip <span class="keyword">install</span> -U pip</span><br></pre></td></tr></table></figure></p><p>如果pip出现有问题,或者你花了很长的时间想用pip安装,例如使用下面这种方式:<br><figure class="highlight lsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install Django==<span class="number">1.8</span><span class="number">.16</span></span><br></pre></td></tr></table></figure></p><p>如果你刚好安装成功,那么恭喜你;如果不是,那么我们就要使用另外一种方法; </p><ol start="3"><li>下载安装</li></ol><p><a href="https://github.com/django/django/archive/master.tar.gz" target="_blank" rel="noopener">gzip压缩包</a></p><p>或者:<br><figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="keyword">clone</span> <span class="title">https</span>://github.com/django/django.git</span><br></pre></td></tr></table></figure></p><p>下载完成之后:<br><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">tar -xvf django-master<span class="selector-class">.tar</span><span class="selector-class">.gz</span></span><br><span class="line">cd django-master</span><br><span class="line">python setup<span class="selector-class">.py</span> install</span><br></pre></td></tr></table></figure></p><p>会出现下面的问题:<br><img src="http://static.zybuluo.com/usiege/skgzjd12wfs2u973aidsrk7o/image_1bt9ib15m8juqh01adb1hlb154k9.png" alt="image_1bt9ib15m8juqh01adb1hlb154k9.png-97.5kB"><br>继续找:<br>Because you’re trying to install it on Python2, but the latest version of Django requires Python 3;<br>所以使用安装方法:<br><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip3 <span class="keyword">install</span> -e django</span><br></pre></td></tr></table></figure></p><p>这个仍然是联网安装,但是貌似<code>pytz</code>并不能连接上,vpn也不行;<br>所以:<br><figure class="highlight vim"><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"><span class="keyword">cd</span> django</span><br><span class="line"><span class="keyword">python3</span> setup.<span class="keyword">py</span> install</span><br></pre></td></tr></table></figure></p><p>终于,你的django完成了;</p><p>续:<br>隔天使用以上的所有方法均可以,可能是十九大开会期间被墙掉了吧。<br><img src="http://static.zybuluo.com/usiege/06h0phv3szekmv2l4x2cmurb/image_1btbid9ijfnd1q2i15npd78l9p9.png" alt="image_1btbid9ijfnd1q2i15npd78l9p9.png-253.6kB"></p>]]></content>
<summary type="html">
<p>django<br>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="python" scheme="http://charlesblog.site/tags/python/"/>
<category term="django" scheme="http://charlesblog.site/tags/django/"/>
</entry>
<entry>
<title>你的pod不工作了吗?</title>
<link href="http://charlesblog.site/2017/10/17/%E4%BD%A0%E7%9A%84pod%E4%B8%8D%E5%B7%A5%E4%BD%9C%E4%BA%86%E5%90%97%EF%BC%9F/"/>
<id>http://charlesblog.site/2017/10/17/你的pod不工作了吗?/</id>
<published>2017-10-17T03:03:00.000Z</published>
<updated>2018-05-07T02:17:42.735Z</updated>
<content type="html"><![CDATA[<p>最近公司的项目需要添加几个依赖库,用pod更新的时候发现一直卡在了<br><figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Setting up CocoaPods <span class="keyword">master</span> <span class="title">repo</span></span><br></pre></td></tr></table></figure></p><a id="more"></a><p>继而是漫长的等待,在这个期间我不知道它发生了什么。</p><p>在这种等待中,程序员一般会选择做一些别的事情。于是我上网验证了一下我的行为,结论告诉我:</p><p>1.我要开个VPN;</p><p>2.我需要重新安装一下pod,因为它已经不工作了;</p><p>首先要先检查一下ruby源:</p><figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">gem sources -l</span></span><br></pre></td></tr></table></figure><p>返回的结果是<a href="https://rubygems.org/,如果你在网上找到过其他源并且修改过它,并且你不确定你的源是否可以使用的话,那么请修改回来,买个VPN,这会让你节省很多不必要的劳动,你可以用以下代码修改源:" target="_blank" rel="noopener">https://rubygems.org/,如果你在网上找到过其他源并且修改过它,并且你不确定你的源是否可以使用的话,那么请修改回来,买个VPN,这会让你节省很多不必要的劳动,你可以用以下代码修改源:</a></p><figure class="highlight livecodeserver"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#移除旧源</span></span><br><span class="line">gem sources <span class="comment">--remove 旧源址</span></span><br><span class="line"><span class="comment">#添加新源</span></span><br><span class="line">gem sources -<span class="keyword">a</span> <span class="keyword">https</span>://rubygems.org/</span><br></pre></td></tr></table></figure><p>PS:请确保你的源可用!!!</p><p>接着如果你没有安装pod,请执行:</p><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo gem <span class="keyword">install</span> cocoapods</span><br></pre></td></tr></table></figure><p>如果你已经安装pod,请执行:</p><figure class="highlight arduino"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pod <span class="built_in">setup</span></span><br></pre></td></tr></table></figure><p>这个操作结束之后,又重现了一个漫长的等待过程,那么我们要清楚它是否在认真工作,请打开另外一个终端,我们要检查一下进度:</p><figure class="highlight jboss-cli"><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"><span class="comment">#进入到pod目录</span></span><br><span class="line"><span class="keyword">cd</span> ~<span class="string">/.cocoapods</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#检查当前文件下所有文件的大小,此后如果你不放心,可以分时段检查一下</span></span><br><span class="line">du -sh *</span><br></pre></td></tr></table></figure><p>这个过程会很漫长,取决于你VPN的速度,最后我这边出结果会反馈绿色的文字,Setup completed!文件总大小是1.2G,所以还是耐心的等待吧。。。</p><p>另外还有一点,如果上述<code>pod setup</code>出现红色的错误信息,也有可能是gem没有到最新版本,那么你还需要用你的VPN更新一下gem到最新;<br><figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo gem <span class="keyword">update</span> --<span class="keyword">system</span></span><br></pre></td></tr></table></figure></p><p>PS:顺便记一下寻找库代码<br><figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">pod search AFNetworking</span></span><br></pre></td></tr></table></figure></p><p>这个时候会遇到这样的提示:<br><figure class="highlight sqf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[!] Unable <span class="keyword">to</span> <span class="built_in">find</span> a pod <span class="keyword">with</span> <span class="built_in">name</span>, author, summary, <span class="built_in">or</span> descriptionmatching `AFNetworking`</span><br></pre></td></tr></table></figure></p><p>你需要做如下操作,再进行搜索:<br><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rm ~<span class="regexp">/Library/</span>Caches<span class="regexp">/CocoaPods/</span>search_index.json</span><br></pre></td></tr></table></figure></p><p>最后你将如愿以偿,感谢亲人:<br><figure class="highlight gams"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="title">Creating</span></span> search index <span class="keyword">for</span> spec repo <span class="string">'master'</span>.. Done!</span><br></pre></td></tr></table></figure></p>]]></content>
<summary type="html">
<p>最近公司的项目需要添加几个依赖库,用pod更新的时候发现一直卡在了<br><figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Setting up CocoaPods <span class="keyword">master</span> <span class="title">repo</span></span><br></pre></td></tr></table></figure></p>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="CocaoPods" scheme="http://charlesblog.site/tags/CocaoPods/"/>
</entry>
<entry>
<title>git checkout 与 reset</title>
<link href="http://charlesblog.site/2017/08/18/git%20checkout%20%E4%B8%8E%20reset/"/>
<id>http://charlesblog.site/2017/08/18/git checkout 与 reset/</id>
<published>2017-08-18T09:34:00.000Z</published>
<updated>2018-05-07T02:17:42.733Z</updated>
<content type="html"><![CDATA[<p>公司最近的一次App提交过程中遇到的一些问题,现贴在这里,有检索到本篇的朋友们可借鉴。<br><a id="more"></a></p><p>首先是上传到iTunes Connect构建版本,点击以下蓝色按钮,之后会有苹果为你的代码进行检查:</p><p><img src="http://static.zybuluo.com/usiege/n72bt0t4wwh45zw5c0kjcv01/image_1bu7k3nt22m3cmearq636qua9.png" alt="image_1bu7k3nt22m3cmearq636qua9.png-14.8kB"></p><p>本人在ios11上做了提交,发现问题进行分类:</p><ol><li>第一个是第三方库存在x86_64,i386的链接库,有以下问题:</li></ol><figure class="highlight subunit"><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">iTunes Store Operation Failed</span><br><span class="line"><span class="keyword">ERROR </span>ITMS<span class="string">-90087</span>: "Unsupported Architectures. The executable for LeWaiJiao.app/Frameworks/GCDWebServers.framework contains unsupported architectures '[x86_64, i386]'."</span><br></pre></td></tr></table></figure><p>PS:以下所有翻译来源于欧路词典,粘贴过来的,仅供参考;<br><figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">iTunes Store Operation Failed</span><br><span class="line"><span class="keyword">ERROR </span>ITMS<span class="string">-90209</span>: "Invalid Segment Alignment. The app binary at 'LeWaiJiao.app/Frameworks/GCDWebServers.framework/GCDWebServers' does not have proper segment alignment. Try rebuilding the app with the latest Xcode version."</span><br><span class="line">无效段对齐。应用程序二进制的“lewaijiao。应用程序/框架/ gcdwebservers。框架/ gcdwebservers”没有正确对齐。尝试用新的Xcode版本重建应用程序。</span><br></pre></td></tr></table></figure></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">iTunes Store Operation Failed</span><br><span class="line">ERROR ITMS-90125: "The binary is invalid. The encryption info in the LC_ENCRYPTION_INFO <span class="keyword">load</span> command <span class="keyword">is</span> either <span class="keyword">missing</span> <span class="keyword">or</span> invalid, <span class="keyword">or</span> the <span class="built_in">binary</span> <span class="keyword">is</span> already encrypted. This <span class="built_in">binary</span> does <span class="keyword">not</span> seem <span class="keyword">to</span> have been built <span class="keyword">with</span> Apple<span class="string">'s linker."</span></span><br><span class="line"><span class="string">“二进制无效。在lc_encryption_info负荷指令加密信息丢失或无效,或是已经加密的二进制。这个二进制文件似乎没有用苹果的链接器构建。”</span></span><br></pre></td></tr></table></figure><figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">iTunes Store Operation Failed</span><br><span class="line">WARNING ITMS-90080: "The executable 'Payload/LeWaiJiao.app/Frameworks/GCDWebServers.framework' is not a Position Independent Executable. Please ensure that your <span class="keyword">build</span> settings are configured <span class="keyword">to</span> <span class="keyword">create</span> PIE executables. <span class="keyword">For</span> more information refer <span class="keyword">to</span> Technical Q&A QA1788 - Building a <span class="built_in">Position</span> Independent Executable <span class="keyword">in</span> the iOS Developer Library.<span class="string">"</span></span><br><span class="line"><span class="string">“可执行的有效载荷/ lewaijiao。应用程序/框架/ gcdwebservers。框架”不是一个独立的可执行文件的位置。请确保您的构建设置配置为创建饼可执行文件。更多信息请参阅技术问答qa1788在iOS开发者库位置独立的可执行的建筑。”</span></span><br></pre></td></tr></table></figure><figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ERROR </span>ITMS<span class="string">-90362</span>: "Invalid Info.plist value. The value for the key 'MinimumOSVersion' in bundle ***.app/Frameworks/SDK.framework is invalid. The minimum value is 8.0"</span><br></pre></td></tr></table></figure><p>后面这个<strong>90362</strong>貌似是连带问题,定位的时候发现与最小版本无关,所以一同被解决了;</p><p>解决方法呢是在该工程里添加脚本处理这些被添加进来的第三方库,如下:<br><img src="http://static.zybuluo.com/usiege/mqh6ttzi6hsixpddv5nmcu03/image_1bu7kmq06140t1nmhkf11sfq1civm.png" alt="image_1bu7kmq06140t1nmhkf11sfq1civm.png-235.5kB"><br><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><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></pre></td><td class="code"><pre><span class="line">APP_PATH=<span class="string">"<span class="variable">${TARGET_BUILD_DIR}</span>/<span class="variable">${WRAPPER_NAME}</span>"</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># This script loops through the frameworks embedded in the application and</span></span><br><span class="line"><span class="comment"># removes unused architectures.</span></span><br><span class="line">find <span class="string">"<span class="variable">$APP_PATH</span>"</span> -name <span class="string">'*.framework'</span> -<span class="built_in">type</span> d | <span class="keyword">while</span> <span class="built_in">read</span> -r FRAMEWORK</span><br><span class="line"><span class="keyword">do</span></span><br><span class="line">FRAMEWORK_EXECUTABLE_NAME=$(defaults <span class="built_in">read</span> <span class="string">"<span class="variable">$FRAMEWORK</span>/Info.plist"</span> CFBundleExecutable)</span><br><span class="line">FRAMEWORK_EXECUTABLE_PATH=<span class="string">"<span class="variable">$FRAMEWORK</span>/<span class="variable">$FRAMEWORK_EXECUTABLE_NAME</span>"</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">"Executable is <span class="variable">$FRAMEWORK_EXECUTABLE_PATH</span>"</span></span><br><span class="line"></span><br><span class="line">EXTRACTED_ARCHS=()</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> ARCH <span class="keyword">in</span> <span class="variable">$ARCHS</span></span><br><span class="line"><span class="keyword">do</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">"Extracting <span class="variable">$ARCH</span> from <span class="variable">$FRAMEWORK_EXECUTABLE_NAME</span>"</span></span><br><span class="line">lipo -extract <span class="string">"<span class="variable">$ARCH</span>"</span> <span class="string">"<span class="variable">$FRAMEWORK_EXECUTABLE_PATH</span>"</span> -o <span class="string">"<span class="variable">$FRAMEWORK_EXECUTABLE_PATH</span>-<span class="variable">$ARCH</span>"</span></span><br><span class="line">EXTRACTED_ARCHS+=(<span class="string">"<span class="variable">$FRAMEWORK_EXECUTABLE_PATH</span>-<span class="variable">$ARCH</span>"</span>)</span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">"Merging extracted architectures: <span class="variable">${ARCHS}</span>"</span></span><br><span class="line">lipo -o <span class="string">"<span class="variable">$FRAMEWORK_EXECUTABLE_PATH</span>-merged"</span> -create <span class="string">"<span class="variable">${EXTRACTED_ARCHS[@]}</span>"</span></span><br><span class="line">rm <span class="string">"<span class="variable">${EXTRACTED_ARCHS[@]}</span>"</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">"Replacing original executable with thinned version"</span></span><br><span class="line">rm <span class="string">"<span class="variable">$FRAMEWORK_EXECUTABLE_PATH</span>"</span></span><br><span class="line">mv <span class="string">"<span class="variable">$FRAMEWORK_EXECUTABLE_PATH</span>-merged"</span> <span class="string">"<span class="variable">$FRAMEWORK_EXECUTABLE_PATH</span>"</span></span><br><span class="line"><span class="keyword">done</span></span><br></pre></td></tr></table></figure></p><p>以上代码来源于Google,解决方法经确认iOS11 + Xcode9.0有效;</p><ol start="2"><li>项目有icon不合规定的错误<figure class="highlight subunit"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">iTunes Store Operation Failed</span><br><span class="line"><span class="keyword">ERROR </span>ITMS<span class="string">-90717</span>: "Invalid App Store Icon. The App Store Icon in the asset catalog in 'LeWaiJiao.app' can't be transparent nor contain an alpha channel."</span><br><span class="line">无效应用程序商店图标。在资产目录中的lewaijiao App Store图标,应用程序不能透明也包含alpha通道。”</span><br></pre></td></tr></table></figure></li></ol><p>该错误原因是上传的icon不符合苹果规定,公司项目存在的问题是1.使用了圆角;2.有透明alpha通道;<br>解决方法自然容易了,找设计重新做,自己解决的话第二个可以DIY,如下:</p><p><img src="http://static.zybuluo.com/usiege/xtde6py269a5m4iusbumms4p/image_1bu7l6vhrvhm51b13pjvrlc0p13.png" alt="image_1bu7l6vhrvhm51b13pjvrlc0p13.png-100.4kB"></p><p>用系统预览打开icon图片,点掉Alpha的勾,再保存就可以了;<br><img src="http://static.zybuluo.com/usiege/yql5tndy4d612fhqfsi9n4l2/image_1bu7l8bt61p6v1mp11csi15ri1dmg1g.png" alt="image_1bu7l8bt61p6v1mp11csi15ri1dmg1g.png-128.6kB"></p><ol start="3"><li>提交上传结束后又出现了一个问题</li></ol><figure class="highlight stata"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">App</span> Installation failed, <span class="keyword">No</span> code signature found.</span><br></pre></td></tr></table></figure><p>真机无法运行了!这个问题纯属偶然,所以继续解决;打开终端,输入</p><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo chmod -R <span class="number">777</span> <span class="regexp">/Applications/</span>Xcode.app<span class="regexp">/Contents/</span>Developer<span class="regexp">/Platforms/i</span>PhoneOS.platform<span class="regexp">/Developer/</span>SDKs<span class="regexp">/iPhoneOS.sdk</span></span><br></pre></td></tr></table></figure><p>修改文件权限,然后修改字段属性,打开:</p><p><strong>/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/SDKSettings.plist</strong></p><p>,修改 <strong>CODE_SIGNING_REQUIRED</strong> 字段为 <strong>YES</strong> ,保存;</p>]]></content>
<summary type="html">
<p>公司最近的一次App提交过程中遇到的一些问题,现贴在这里,有检索到本篇的朋友们可借鉴。<br>
</summary>
<category term="coder" scheme="http://charlesblog.site/categories/coder/"/>
<category term="git" scheme="http://charlesblog.site/tags/git/"/>
</entry>
</feed>