-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
455 lines (216 loc) · 140 KB
/
search.xml
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
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>Flutter 对齐与相对定位</title>
<link href="/2022/05/29/fe66a5355c28.html"/>
<url>/2022/05/29/fe66a5355c28.html</url>
<content type="html"><![CDATA[<h1 id="对齐与相对定位(Align)"><a href="#对齐与相对定位(Align)" class="headerlink" title="对齐与相对定位(Align)"></a>对齐与相对定位(Align)</h1><p>定义</p><figure class="highlight dart"><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">Align({</span><br><span class="line"> <span class="keyword">this</span>.alignment = Alignment.center,</span><br><span class="line"> <span class="keyword">this</span>.widthFactor,</span><br><span class="line"> <span class="keyword">this</span>.heightFactor,</span><br><span class="line"> Widget child,</span><br><span class="line">})</span><br></pre></td></tr></table></figure><ul><li>alignment : 需要一个AlignmentGeometry类型的值,表示子组件在父组件中的起始位置。AlignmentGeometry 是一个抽象类,它有两个常用的子类:Alignment和 FractionalOffset,我们将在下面的示例中详细介绍。</li><li>widthFactor和heightFactor是用于确定Align 组件本身宽高的属性;<ul><li>它们是两个缩放因子,会分别乘以子元素的宽、高,最终的结果就是Align 组件的宽高。</li><li>如果值为null,则组件的宽高将会占用尽可能多的空间。</li></ul></li></ul><span id="more"></span><figure class="highlight dart"><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">Container(</span><br><span class="line"> height: <span class="number">120.0</span>, <span class="comment">// 高度父组件决定</span></span><br><span class="line"> <span class="comment">// width: 120.0, // 宽度使用align确定, 优先级大于子组件</span></span><br><span class="line"> color: Colors.blue.shade50,</span><br><span class="line"> child: Align(</span><br><span class="line"> widthFactor: <span class="number">3</span>, <span class="comment">// 宽度为自身的3倍, </span></span><br><span class="line"> <span class="comment">// 当align和父组件都设置了的话,父组件的生效</span></span><br><span class="line"> alignment: Alignment.topRight, <span class="comment">// 对齐位置是右上角, 即子组件和父组件的右上角对齐</span></span><br><span class="line"> child: FlutterLogo(</span><br><span class="line"> size: <span class="number">60</span>,</span><br><span class="line"> ),</span><br><span class="line"> ),</span><br><span class="line">);</span><br></pre></td></tr></table></figure><img src="/2022/05/29/fe66a5355c28/16538377129777.jpg" class=""><h3 id="Alignment"><a href="#Alignment" class="headerlink" title="Alignment"></a>Alignment</h3><p>定义:<code>Alignment(this.x, this.y)</code><br>Alignment继承自AlignmentGeometry,表示矩形内的一个点,他有两个属性x、y,分别表示在水平和垂直方向的偏移<br>Alignment Widget会以矩形的中心点作为坐标原点,即Alignment(0.0, 0.0) 。x、y的值从-1到1分别代表矩形左边到右边的距离和顶部到底边的距离,因此2个水平(或垂直)单位则等于矩形的宽(或高); 如Alignment(-1.0, -1.0) 代表矩形的左侧顶点</p><p>具体偏移为<br>offset(x, y) = (Alignment.x * childWidth / 2 + childWidth / 2, Alignment.y * childHeight / 2 + childHeight / 2)</p><figure class="highlight dart"><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">Container(</span><br><span class="line"> height: <span class="number">120.0</span>, <span class="comment">// 高度父组件决定</span></span><br><span class="line"> <span class="comment">// width: 120.0, // 宽度使用align确定, 优先级大于子组件</span></span><br><span class="line"> color: Colors.blue.shade50,</span><br><span class="line"> child: Align(</span><br><span class="line"> widthFactor: <span class="number">3</span>, <span class="comment">// 宽度为自身的3倍, </span></span><br><span class="line"> <span class="comment">// 当align和父组件都设置了的话,父组件的生效</span></span><br><span class="line"> alignment: Alignment(<span class="number">2</span>, <span class="number">0</span>), <span class="comment">// 对齐位置为</span></span><br><span class="line"> child: FlutterLogo(</span><br><span class="line"> size: <span class="number">60</span>,</span><br><span class="line"> ),</span><br><span class="line"> ),</span><br><span class="line">);</span><br></pre></td></tr></table></figure><img src="/2022/05/29/fe66a5355c28/16538380684489.jpg" class=""><h3 id="FractionalOffset"><a href="#FractionalOffset" class="headerlink" title="FractionalOffset"></a>FractionalOffset</h3><p>FractionalOffset 继承自 Alignment,它和 Alignment唯一的区别就是坐标原点不同!FractionalOffset 的坐标原点为矩形的左侧顶点,这和布局系统的一致,所以理解起来会比较容易。<br>偏移指的是x y的偏移;</p><p>转换公式为:<br>实际偏移 = (FractionalOffset.x * childWidth, FractionalOffset.y * childHeight)</p><figure class="highlight dart"><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">Align(</span><br><span class="line"> alignment: FractionalOffset(<span class="number">0.5</span>, <span class="number">1</span>),</span><br><span class="line"> child: FlutterLogo(</span><br><span class="line"> size: <span class="number">60</span>,</span><br><span class="line">),</span><br></pre></td></tr></table></figure><img src="/2022/05/29/fe66a5355c28/16538386017539.jpg" class=""><p>可以看到,Align和Stack/Positioned都可以用于指定子元素相对于父元素的偏移,但它们还是有两个主要区别:</p><p>定位参考系统不同;Stack/Positioned定位的的参考系可以是父容器矩形的四个顶点;而Align则需要先通过alignment 参数来确定坐标原点,不同的alignment会对应不同原点,最终的偏移是需要通过alignment的转换公式来计算出。<br>Stack可以有多个子元素,并且子元素可以堆叠,而Align只能有一个子元素,不存在堆叠。</p><h3 id="Center"><a href="#Center" class="headerlink" title="Center"></a>Center</h3><figure class="highlight dart"><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">Center({</span><br><span class="line"> <span class="built_in">double?</span> widthFactor, </span><br><span class="line"> <span class="built_in">double?</span> heightFactor, </span><br><span class="line"> Widget? child </span><br><span class="line">})</span><br></pre></td></tr></table></figure><p>可以看到Center继承自Align,它比Align只少了一个alignment 参数;由于Align的构造函数中alignment 值为Alignment.center,所以,我们可以认为Center组件其实是对齐方式确定(Alignment.center)了的Align。</p><figure class="highlight dart"><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">DecoratedBox(</span><br><span class="line"> decoration: BoxDecoration(color: Colors.red),</span><br><span class="line"> child: Center(</span><br><span class="line"> child: Text(<span class="string">"xxx"</span>),</span><br><span class="line"> ),</span><br><span class="line">),</span><br><span class="line">DecoratedBox(</span><br><span class="line"> decoration: BoxDecoration(color: Colors.red),</span><br><span class="line"> child: Center(</span><br><span class="line"> widthFactor: <span class="number">1</span>,</span><br><span class="line"> heightFactor: <span class="number">1</span>,</span><br><span class="line"> child: Text(<span class="string">"xxx"</span>),</span><br><span class="line"> ),</span><br><span class="line">)</span><br></pre></td></tr></table></figure><img src="/2022/05/29/fe66a5355c28/16538388400806.jpg" class=""><p>两种偏移类Alignment 和FractionalOffset,区别及各自的坐标转化公式</p><p>在需要制定一些精确的偏移时应优先使用FractionalOffset,因为它的坐标原点和布局系统相同,能更容易算出实际偏移。</p>]]></content>
<tags>
<tag> iOS </tag>
<tag> Flutter </tag>
<tag> Layout </tag>
</tags>
</entry>
<entry>
<title>Flutter 层叠布局</title>
<link href="/2022/05/28/68dbbde40c84.html"/>
<url>/2022/05/28/68dbbde40c84.html</url>
<content type="html"><![CDATA[<h1 id="层叠布局"><a href="#层叠布局" class="headerlink" title="层叠布局"></a>层叠布局</h1><p>层叠布局和 Web 中的绝对定位布局是相似的,子组件可以根据距父容器四个角的位置来确定自身的位置。层叠布局允许子组件按照代码中声明的顺序堆叠起来。<br>Flutter中使用Stack和Positioned这两个组件来配合实现绝对定位。<br>Stack允许子组件堆叠,而Positioned用于根据Stack的四个角来确定子组件的位置。</p><table><thead><tr><th align="center">Flutter</th><th align="center">SwiftUI</th></tr></thead><tbody><tr><td align="center">Row</td><td align="center">HStack</td></tr><tr><td align="center">Column</td><td align="center">VStack</td></tr><tr><td align="center">Stack</td><td align="center">ZStack</td></tr></tbody></table><span id="more"></span><h3 id="Stack"><a href="#Stack" class="headerlink" title="Stack"></a>Stack</h3><p>定义</p><figure class="highlight dart"><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">Stack({</span><br><span class="line"> <span class="keyword">this</span>.alignment = AlignmentDirectional.topStart,</span><br><span class="line"> <span class="keyword">this</span>.textDirection,</span><br><span class="line"> <span class="keyword">this</span>.fit = StackFit.loose,</span><br><span class="line"> <span class="keyword">this</span>.clipBehavior = Clip.hardEdge,</span><br><span class="line"> <span class="built_in">List</span><Widget> children = <span class="keyword">const</span> <Widget>[],</span><br><span class="line">})</span><br></pre></td></tr></table></figure><ul><li>alignment:此参数决定如何去对齐没有定位(没有使用Positioned)或部分定位的子组件。所谓部分定位,在这里特指没有在某一个轴上定位:left、right为横轴,top、bottom为纵轴,只要包含某个轴上的一个定位属性就算在该轴上有定位。</li><li>textDirection:和Row、Wrap的textDirection功能一样,都用于确定alignment对齐的参考系,即:textDirection的值为.ltr,则alignment的start代表左,end代表右,即从左往右的顺序;textDirection的值为.rtl,则alignment的start代表右,end代表左,即从右往左的顺序。</li><li>fit:此参数用于确定没有定位的子组件如何去适应Stack的大小。StackFit.loose表示使用子组件的大小,StackFit.expand表示扩伸到Stack的大小。</li><li>clipBehavior:此属性决定对超出Stack显示空间的部分如何剪裁,Clip枚举类中定义了剪裁的方式,Clip.hardEdge 表示直接剪裁,不应用抗锯齿</li></ul><h3 id="Positioned"><a href="#Positioned" class="headerlink" title="Positioned"></a>Positioned</h3><figure class="highlight dart"><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">Positioned({</span><br><span class="line"> <span class="keyword">this</span>.left, </span><br><span class="line"> <span class="keyword">this</span>.top,</span><br><span class="line"> <span class="keyword">this</span>.right,</span><br><span class="line"> <span class="keyword">this</span>.bottom,</span><br><span class="line"> <span class="keyword">this</span>.width,</span><br><span class="line"> <span class="keyword">this</span>.height,</span><br><span class="line"> <span class="keyword">required</span> Widget child,</span><br><span class="line">})</span><br></pre></td></tr></table></figure><ul><li>left、top 、right、 bottom分别代表离Stack左、上、右、底四边的距离。 </li><li>width和height用于指定需要定位元素的宽度和高度。<br>注意,Positioned的width、height 和其它地方的意义稍微有点区别,此处用于配合left、top 、right、 bottom来定位组件,举个例子,在水平方向时,你只能指定left、right、width三个属性中的两个,如指定left和width后,right会自动算出(left+width),如果同时指定三个属性则会报错,垂直方向同理。</li></ul>]]></content>
<tags>
<tag> iOS </tag>
<tag> Flutter </tag>
<tag> Layout </tag>
</tags>
</entry>
<entry>
<title>iOS Lock</title>
<link href="/2022/05/27/ab7dd047758f.html"/>
<url>/2022/05/27/ab7dd047758f.html</url>
<content type="html"><![CDATA[<h1 id="锁-🔒"><a href="#锁-🔒" class="headerlink" title="锁 🔒"></a>锁 🔒</h1><p>锁用于解决多线程间资源共享的安全问题</p><p>分类:</p><ul><li>自旋锁(Spinlock): 即忙等,类似 do-while,会一直占着CPU、内存等即忙碌状态</li><li>互斥锁(Mutex): 闲等,即锁的线程处于休眠状态<ul><li>非递归锁(non-recursive mutex)或称不可重入互斥锁(non-reentrant mutex): 同一时刻只能被一条线程所拥有</li><li>可递归锁(recursive mutex)或称可重入互斥锁(reentrant mutex): 同一时刻能被多条线程所拥有</li></ul></li><li>读写锁: 多读单写、读和写要互斥,有空再补<span id="more"></span></li></ul><h3 id="iOS中常见方案:"><a href="#iOS中常见方案:" class="headerlink" title="iOS中常见方案:"></a>iOS中常见方案:</h3><h4 id="OSSpinLock-自旋锁"><a href="#OSSpinLock-自旋锁" class="headerlink" title="OSSpinLock: 自旋锁"></a>OSSpinLock: 自旋锁</h4><p> 自iOS10移除,被os_unfair_lock替代,因为优先级反转(Priority inversion)问题,优先级高的线程会被系统持续优先调度,所以优先级低的线程一直在等待,无法执行任务<br> <figure class="highlight objc"><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">OSSpinLock lock = OS_SPINLOCK_INIT; <span class="comment">// 初始化</span></span><br><span class="line">OSSpinLockLock(&lock); <span class="comment">// 加锁</span></span><br><span class="line">OSSpinLockUnlock(&lock); <span class="comment">// 解锁</span></span><br><span class="line">OSSpinLockTry(&lock); <span class="comment">// 尝试上锁,false即失败,锁被其他线程持有</span></span><br></pre></td></tr></table></figure></p><h4 id="os-unfair-lock-互斥锁"><a href="#os-unfair-lock-互斥锁" class="headerlink" title="os_unfair_lock: 互斥锁"></a>os_unfair_lock: 互斥锁</h4><p> iOS10开始支持,用以替代不安全的OSSpinLock;<br> 等待锁的线程会处于休眠状态,<br> <figure class="highlight objc"><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">os_unfair_lock unfairLock = OS_UNFAIR_LOCK_INIT; <span class="comment">// 初始化</span></span><br><span class="line">os_unfair_lock_lock(&unfairLock); <span class="comment">// 加锁</span></span><br><span class="line">os_unfair_lock_unlock(&unfairLock); <span class="comment">// 解锁</span></span><br><span class="line">os_unfair_lock_trylock(&unfairLock); <span class="comment">// 尝试上锁</span></span><br></pre></td></tr></table></figure></p><h4 id="pthread-mutex-互斥锁"><a href="#pthread-mutex-互斥锁" class="headerlink" title="pthread_mutex: 互斥锁"></a>pthread_mutex: 互斥锁</h4><p> 线程在等待锁时会处于休眠状态<br> <figure class="highlight objc"><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">//非递归</span></span><br><span class="line">pthread_mutex_t lock0;</span><br><span class="line">pthread_mutex_init(&lock0, <span class="literal">NULL</span>); <span class="comment">// 初始化</span></span><br><span class="line">pthread_mutex_lock(&lock0); <span class="comment">// 加锁</span></span><br><span class="line"><span class="comment">// ...</span></span><br><span class="line">pthread_mutex_unlock(&lock0); <span class="comment">// 解锁</span></span><br><span class="line">pthread_mutex_destroy(&lock0); <span class="comment">// 释放</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//递归</span></span><br><span class="line">pthread_mutex_t lock1;</span><br><span class="line">pthread_mutexattr_t attr; <span class="comment">// 用于设置锁的类型</span></span><br><span class="line">pthread_mutexattr_init(&attr);</span><br><span class="line">pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); <span class="comment">// 递归</span></span><br><span class="line">pthread_mutex_init(&lock1, &attr); <span class="comment">// 初始化</span></span><br><span class="line">pthread_mutexattr_destroy(&attr); <span class="comment">// 释放</span></span><br><span class="line">pthread_mutex_lock(&lock1); <span class="comment">// 加锁</span></span><br><span class="line"><span class="comment">// ...</span></span><br><span class="line">pthread_mutex_unlock(&lock1); <span class="comment">// 解锁</span></span><br><span class="line">pthread_mutex_destroy(&lock1); <span class="comment">// 释放</span></span><br></pre></td></tr></table></figure></p><h4 id="NSLock-再熟悉不过的吧,遵循NSLocking协议"><a href="#NSLock-再熟悉不过的吧,遵循NSLocking协议" class="headerlink" title="NSLock: 再熟悉不过的吧,遵循NSLocking协议"></a>NSLock: 再熟悉不过的吧,遵循NSLocking协议</h4> <figure class="highlight objc"><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="built_in">NSLock</span> *aLock = [[<span class="built_in">NSLock</span> alloc] init];</span><br><span class="line">[aLock lock];</span><br><span class="line">[aLock unlock]; </span><br><span class="line">[aLock tryLock]; <span class="comment">// 尝试加锁 返回Bool</span></span><br><span class="line">[aLock lockBeforeDate: <span class="built_in">NSDate</span>.date]; <span class="comment">// 能否在指定时间点之前获取锁</span></span><br></pre></td></tr></table></figure><h4 id="NSCondition-互斥锁,遵循NSLocking协议"><a href="#NSCondition-互斥锁,遵循NSLocking协议" class="headerlink" title="NSCondition: 互斥锁,遵循NSLocking协议"></a>NSCondition: 互斥锁,遵循NSLocking协议</h4><p> 存在虚假唤醒问题,</p><figure class="highlight objc"><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></pre></td><td class="code"><pre><span class="line">- (<span class="type">void</span>)testConditionLock {</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < <span class="number">50</span>; i ++) {</span><br><span class="line"> <span class="built_in">dispatch_async</span>(dispatch_get_global_queue(<span class="number">0</span>, <span class="number">0</span>), ^{</span><br><span class="line"> [<span class="keyword">self</span> testProduction];</span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < <span class="number">100</span>; i ++) {</span><br><span class="line"> <span class="built_in">dispatch_async</span>(dispatch_get_global_queue(<span class="number">0</span>, <span class="number">0</span>), ^{</span><br><span class="line"> [<span class="keyword">self</span> testConsumption];</span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">- (<span class="type">void</span>)testProduction {</span><br><span class="line"> [<span class="keyword">self</span>.conditionLock lock]; <span class="comment">// 加锁</span></span><br><span class="line"> <span class="keyword">self</span>.count ++;</span><br><span class="line"> <span class="built_in">NSLog</span>(<span class="string">@"生产了一个, 现有还有 %d 个"</span>, <span class="keyword">self</span>.count);</span><br><span class="line"> [<span class="keyword">self</span>.conditionLock signal]; <span class="comment">// 唤醒一个正在休眠的线程,如果要唤醒多个,需要调用多次。如果没有符合条件的线程则什么也不做。使用时必须已加锁。</span></span><br><span class="line"> [<span class="keyword">self</span>.conditionLock unlock]; <span class="comment">// 解锁</span></span><br><span class="line">}</span><br><span class="line">- (<span class="type">void</span>)testConsumption {</span><br><span class="line"> [<span class="keyword">self</span>.conditionLock lock]; <span class="comment">// 加锁</span></span><br><span class="line"> <span class="keyword">while</span> (<span class="keyword">self</span>.count == <span class="number">0</span>) { </span><br><span class="line"> <span class="comment">// 使用while而非if,是用于解决虚假唤醒(一次signal唤醒多个wait)问题,</span></span><br><span class="line"> <span class="comment">// 即当次线程被唤醒则再去检查count个数是否有值,否则继续进入wait状态,</span></span><br><span class="line"> <span class="comment">// 这样也就被唤醒多个的线程只有一个能正常走出此while循环进入下一步消耗的步骤</span></span><br><span class="line"> [<span class="keyword">self</span>.iCondition wait]; <span class="comment">// 阻塞当前线程,使线程进入休眠,等待唤醒信号。使用时必须已加锁</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">self</span>.count --;</span><br><span class="line"> <span class="built_in">NSLog</span>(<span class="string">@"消耗了一个, 现有还有 %d 个"</span>, <span class="keyword">self</span>.count);</span><br><span class="line"> [<span class="keyword">self</span>.conditionLock unlock]; <span class="comment">// 解锁</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="NSConditionLock:互斥锁,遵循NSLocking协议"><a href="#NSConditionLock:互斥锁,遵循NSLocking协议" class="headerlink" title="NSConditionLock:互斥锁,遵循NSLocking协议"></a>NSConditionLock:互斥锁,遵循NSLocking协议</h4><figure class="highlight objc"><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">var conditionLock = [[<span class="built_in">NSConditionLock</span> alloc] initWithCondition:<span class="number">10</span>]; </span><br><span class="line"><span class="comment">// 初始化,默认给一个条件</span></span><br><span class="line"><span class="comment">// 加锁: 当lockWhenCondition的条件满足当前锁的条件时加锁,比如下面的10,等于初始时的条件10</span></span><br><span class="line"><span class="comment">// 解锁: unlockWithCondition,重置锁的条件,</span></span><br><span class="line"><span class="built_in">dispatch_async</span>(dispatch_get_global_queue(<span class="number">0</span>, <span class="number">0</span>), ^{</span><br><span class="line"> [<span class="keyword">self</span>.conditionLock lockWhenCondition:<span class="number">10</span>]; <span class="comment">// 满足匹配条件时加锁</span></span><br><span class="line"> <span class="built_in">NSLog</span>(<span class="string">@"线程 1"</span>);</span><br><span class="line"> [<span class="keyword">self</span>.conditionLock unlockWithCondition:<span class="number">2</span>]; <span class="comment">// 解锁, 并重置条件</span></span><br><span class="line">});</span><br><span class="line"><span class="built_in">dispatch_async</span>(dispatch_get_global_queue(<span class="number">0</span>, <span class="number">0</span>), ^{</span><br><span class="line"> [<span class="keyword">self</span>.conditionLock lockWhenCondition:<span class="number">2</span>]; <span class="comment">// 满足匹配条件时加锁</span></span><br><span class="line"> <span class="built_in">NSLog</span>(<span class="string">@"线程 2"</span>);</span><br><span class="line"> [<span class="keyword">self</span>.conditionLock unlockWithCondition:<span class="number">1</span>]; <span class="comment">// 解锁, 并重置条件</span></span><br><span class="line">});</span><br><span class="line"><span class="built_in">dispatch_async</span>(dispatch_get_global_queue(<span class="number">0</span>, <span class="number">0</span>), ^{</span><br><span class="line"> [<span class="keyword">self</span>.conditionLock lockWhenCondition:<span class="number">1</span>]; <span class="comment">// 满足匹配条件时加锁</span></span><br><span class="line"> <span class="built_in">NSLog</span>(<span class="string">@"线程 3"</span>);</span><br><span class="line"> [<span class="keyword">self</span>.conditionLock unlockWithCondition:<span class="number">0</span>]; <span class="comment">// 解锁, 并重置条件</span></span><br><span class="line">});</span><br></pre></td></tr></table></figure><h4 id="NSRecursiveLock-可重入互斥锁,遵循NSLocking协议"><a href="#NSRecursiveLock-可重入互斥锁,遵循NSLocking协议" class="headerlink" title="NSRecursiveLock: 可重入互斥锁,遵循NSLocking协议"></a>NSRecursiveLock: 可重入互斥锁,遵循NSLocking协议</h4><p> 递归锁,就是字面意思,可以递归加锁加锁加锁 再解锁解锁解锁的锁<br> <figure class="highlight objc"><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="built_in">dispatch_async</span>(dispatch_get_global_queue(<span class="number">0</span>, <span class="number">0</span>), ^{</span><br><span class="line"> <span class="keyword">static</span> <span class="type">void</span> (^recursiveBlock)(<span class="type">int</span>);</span><br><span class="line"> recursiveBlock = ^(<span class="type">int</span> value){</span><br><span class="line"> <span class="keyword">if</span> (value > <span class="number">0</span>) {</span><br><span class="line"> [<span class="keyword">self</span>.recursiveLock lock]; <span class="comment">// 加锁</span></span><br><span class="line"> <span class="built_in">NSLog</span>(<span class="string">@"value: %d"</span>, value);</span><br><span class="line"> recursiveBlock(value - <span class="number">1</span>);</span><br><span class="line"> [<span class="keyword">self</span>.recursiveLock unlock]; <span class="comment">// 解锁</span></span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> recursiveBlock(<span class="number">10</span>);</span><br><span class="line">});</span><br></pre></td></tr></table></figure></p><h4 id="synchronized-可重入互斥锁,最简单的锁"><a href="#synchronized-可重入互斥锁,最简单的锁" class="headerlink" title="@synchronized: 可重入互斥锁,最简单的锁"></a>@synchronized: 可重入互斥锁,最简单的锁</h4> <figure class="highlight objc"><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="built_in">dispatch_async</span>(dispatch_get_global_queue(<span class="number">0</span>, <span class="number">0</span>), ^{</span><br><span class="line"> <span class="keyword">static</span> <span class="type">void</span> (^recursiveBlock)(<span class="type">int</span>);</span><br><span class="line"> recursiveBlock = ^(<span class="type">int</span> value){</span><br><span class="line"> <span class="keyword">@synchronized</span> (<span class="keyword">self</span>) {</span><br><span class="line"> <span class="keyword">if</span> (value > <span class="number">0</span>) {</span><br><span class="line"> <span class="built_in">NSLog</span>(<span class="string">@"value: %d"</span>, value);</span><br><span class="line"> recursiveBlock(value - <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> recursiveBlock(<span class="number">10</span>);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h4 id="读写锁:也称“共享-互斥锁”、多读者-单写者锁"><a href="#读写锁:也称“共享-互斥锁”、多读者-单写者锁" class="headerlink" title="读写锁:也称“共享-互斥锁”、多读者-单写者锁"></a>读写锁:也称“共享-互斥锁”、多读者-单写者锁</h4><p> 读操作可并发重入,写操作是互斥的,而且读和写的操作也是互斥的。</p><ul><li><p>同一时刻要么写的操作,要么读的操作。</p></li><li><p>若是写,则最多只能有一个线程在写;若是读,则可以多个线程同时进行读</p><figure class="highlight objc"><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="comment">// 并发队列,因为需要多读</span></span><br><span class="line"><span class="built_in">dispatch_queue_t</span> queue = dispatch_queue_create(<span class="string">"pushLock"</span>, DISPATCH_QUEUE_CONCURRENT);</span><br><span class="line"><span class="comment">// 读操作,同步可以直接获取结果</span></span><br><span class="line"><span class="built_in">dispatch_sync</span>(queue, ^{</span><br><span class="line"> <span class="comment">// 读操作</span></span><br><span class="line">});</span><br><span class="line"><span class="comment">// 写操作,栅栏函数可以保证此时只有写操作,异步可以避免耗时操作阻塞线程</span></span><br><span class="line">dispatch_barrier_async(queue, ^{</span><br><span class="line"> <span class="comment">// 写操作,可能耗时</span></span><br><span class="line">});</span><br></pre></td></tr></table></figure></li></ul><h3 id="学术名词百科:"><a href="#学术名词百科:" class="headerlink" title="学术名词百科:"></a>学术名词百科:</h3><p><a href="https://en.wikipedia.org/wiki/Spurious_wakeup">虚假唤醒</a><br><a href="https://zh.wikipedia.org/wiki/%E8%87%AA%E6%97%8B%E9%94%81">自旋锁</a><br><a href="https://zh.wikipedia.org/wiki/%E4%BC%98%E5%85%88%E8%BD%AC%E7%BD%AE">优先级倒置</a></p>]]></content>
<tags>
<tag> iOS </tag>
<tag> Lock </tag>
</tags>
</entry>
<entry>
<title>Flutter 流式布局</title>
<link href="/2022/05/27/f80c8416a26c.html"/>
<url>/2022/05/27/f80c8416a26c.html</url>
<content type="html"><![CDATA[<h1 id="流式布局"><a href="#流式布局" class="headerlink" title="流式布局"></a>流式布局</h1><h3 id="Wrap"><a href="#Wrap" class="headerlink" title="Wrap"></a>Wrap</h3><p>对于Wrap和Flex(包括Row和Column)除了超出显示范围后Wrap会折行外,其它行为基本相同</p><ul><li>spacing:主轴方向子widget的间距</li><li>runSpacing:纵轴方向的间距</li><li>runAlignment:纵轴方向的对齐方式</li></ul><h3 id="Flow"><a href="#Flow" class="headerlink" title="Flow"></a>Flow</h3><p>Flow主要用于一些需要自定义布局策略或性能要求较高(如动画中)的场景</p><span id="more"></span><h5 id="优点:"><a href="#优点:" class="headerlink" title="优点:"></a>优点:</h5><ul><li>性能好;Flow是一个对子组件尺寸以及位置调整非常高效的控件,Flow用转换矩阵在对子组件进行位置调整的时候进行了优化:在Flow定位过后,如果子组件的尺寸或者位置发生了变化,在FlowDelegate中的paintChildren()方法中调用context.paintChild 进行重绘,而context.paintChild在重绘时使用了转换矩阵,并没有实际调整组件位置。</li><li>灵活;由于我们需要自己实现FlowDelegate的paintChildren()方法,所以我们需要自己计算每一个组件的位置,因此,可以自定义布局策略。<h5 id="缺点:"><a href="#缺点:" class="headerlink" title="缺点:"></a>缺点:</h5></li><li>使用复杂。</li><li>Flow 不能自适应子组件大小,必须通过指定父容器大小或实现TestFlowDelegate的getSize返回固定大小。</li></ul><p>可以看到我们主要的任务就是实现paintChildren,它的主要任务是确定每个子widget位置。由于Flow不能自适应子widget的大小,我们通过在getSize返回一个固定大小来指定Flow的大小。</p>]]></content>
<tags>
<tag> iOS </tag>
<tag> Flutter </tag>
<tag> Layout </tag>
</tags>
</entry>
<entry>
<title>Flutter 弹性布局</title>
<link href="/2022/05/26/b7fe3f1c9dfb.html"/>
<url>/2022/05/26/b7fe3f1c9dfb.html</url>
<content type="html"><![CDATA[<h1 id="弹性布局-Flex"><a href="#弹性布局-Flex" class="headerlink" title="弹性布局 (Flex)"></a>弹性布局 (Flex)</h1><p>弹性布局允许子组件按照一定比例来分配父容器空间, 主要通过Flex和Expanded来配合实现。</p><h2 id="Flex"><a href="#Flex" class="headerlink" title="Flex"></a>Flex</h2><p>定义, 相比Row、Column多了两个参数, 其实他们都是继承于Flex;</p><figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> Flex({</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> <span class="keyword">required</span> <span class="keyword">this</span>.direction, <span class="comment">// 布局的方向: 水平、垂直方向</span></span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> <span class="keyword">this</span>.clipBehavior = Clip.none,</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> })</span><br></pre></td></tr></table></figure><span id="more"></span><h2 id="Expanded"><a href="#Expanded" class="headerlink" title="Expanded"></a>Expanded</h2><p>Expanded 只能作为 Flex 的子组件,它可以按比例“扩伸”Flex子组件所占用的空间。因为 Row 和 Column 都继承自 Flex,所以 Expanded 也可以作为它们的孩子。</p><figure class="highlight dart"><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="keyword">const</span> Expanded({</span><br><span class="line"> Key? key,</span><br><span class="line"> <span class="built_in">int</span> flex = <span class="number">1</span>,</span><br><span class="line"> <span class="keyword">required</span> Widget child,</span><br><span class="line">})</span><br></pre></td></tr></table></figure><p>参数:<br>flex参数为弹性系数,如果为 0 或null,则child是没有弹性的,即不会被扩伸占用的空间。如果大于0,所有的Expanded按照其 flex 的比例来分割主轴的全部剩余空间。</p><h3 id="Spacer"><a href="#Spacer" class="headerlink" title="Spacer"></a>Spacer</h3><p>占用指定比例的剩余空间, 是Expanded的一个包装类</p>]]></content>
<tags>
<tag> iOS </tag>
<tag> Flutter </tag>
<tag> Layout </tag>
</tags>
</entry>
<entry>
<title>Flutter 线性布局</title>
<link href="/2022/05/25/19cb93b3048e.html"/>
<url>/2022/05/25/19cb93b3048e.html</url>
<content type="html"><![CDATA[<h1 id="线性布局-Row、Column"><a href="#线性布局-Row、Column" class="headerlink" title="线性布局 (Row、Column)"></a>线性布局 (Row、Column)</h1><p>Row和Column, 即: 水平方向和垂直方向排列子组件;</p><h3 id="构造方法"><a href="#构造方法" class="headerlink" title="构造方法"></a>构造方法</h3><p>两个轴向:</p><ul><li>mainAxis: 主轴, 即本组件主体的方向</li><li>crossAxis: 纵轴, 即垂直于主轴的方向</li></ul><span id="more"></span><h4 id="Row"><a href="#Row" class="headerlink" title="Row"></a>Row</h4><p>主轴: 水平方向</p><figure class="highlight dart"><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">const</span> Row({</span><br><span class="line"> Key? key,</span><br><span class="line"> MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,</span><br><span class="line"> MainAxisSize mainAxisSize = MainAxisSize.max,</span><br><span class="line"> CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,</span><br><span class="line"> TextDirection? textDirection,</span><br><span class="line"> VerticalDirection verticalDirection = VerticalDirection.down,</span><br><span class="line"> TextBaseline? textBaseline, <span class="comment">// NO DEFAULT: we don't know what the text's baseline should be</span></span><br><span class="line"> <span class="built_in">List</span><Widget> children = <span class="keyword">const</span> <Widget>[],</span><br><span class="line"> })</span><br></pre></td></tr></table></figure><h4 id="Column"><a href="#Column" class="headerlink" title="Column"></a>Column</h4><p>主轴: 垂直方向</p><figure class="highlight dart"><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">const</span> Column({</span><br><span class="line"> Key? key,</span><br><span class="line"> MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,</span><br><span class="line"> MainAxisSize mainAxisSize = MainAxisSize.max,</span><br><span class="line"> CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,</span><br><span class="line"> TextDirection? textDirection,</span><br><span class="line"> VerticalDirection verticalDirection = VerticalDirection.down,</span><br><span class="line"> TextBaseline? textBaseline,</span><br><span class="line"> <span class="built_in">List</span><Widget> children = <span class="keyword">const</span> <Widget>[],</span><br><span class="line"> })</span><br></pre></td></tr></table></figure><p>可以发现构造方法基本一样, 接下来看下具体参数的作用</p><h3 id="参数大致含义"><a href="#参数大致含义" class="headerlink" title="参数大致含义"></a>参数大致含义</h3><ul><li>mainAxisAlignment: 表示子组件在主轴(Row为水平方向)的对齐方式, 参考系textDirection<ul><li>.start: 表示沿textDirection阅读方向的初始方向对齐</li><li>.end: 和.start正好相反</li><li>.center: 表示居中对齐</li><li>.spaceBetween: 平均分控件之间 0:x:x:0</li><li>.spaceAround: 平均分周围 x:xx:xx:x</li><li>.spaceEvenly: 平均分所有间隙 x:x:x:x</li></ul></li><li>mainAxisSize: 表示在主轴(Row为水平方向)的占用空间<ul><li>.max: 表示尽可能多的占用水平方向的空间,此时无论子 widgets 实际占用多少水平空间,Row的宽度始终等于水平方向的最大宽度;</li><li>.min: 表示尽可能少的占用水平空间,当子组件没有占满水平剩余空间,则Row的实际宽度等于所有子组件占用的的水平空间;</li></ul></li><li>crossAxisAlignment: 表示子组件在纵轴(Row为垂直方向)的对齐方式, 高度等于子组件高度中最大值, 参考系是verticalDirection<ul><li>.start</li><li>.end</li><li>.center</li><li>.stretch</li><li>.baseline</li></ul></li><li>textDirection: 表示主轴(Row为水平)的布局方向(阅读方向)<ul><li>.ltr: 中文、英语</li><li>.rtl: 阿拉伯语、Hebrew</li></ul></li><li>verticalDirection: 表示纵轴(Row为垂直)的布局方向<ul><li>.up: 表示从底部到顶部, start在底部</li><li>.down: 表示从顶部到底部, start在顶部</li></ul></li><li>textBaseline: 基线对齐</li><li>children: 子组件数组</li></ul><h3 id="demo"><a href="#demo" class="headerlink" title="demo"></a>demo</h3><p>Row和Column都只会在主轴方向占用尽可能大的空间,而纵轴的长度则取决于子组件长度中最大的, 比如在Row的高度, Column的宽度等</p><figure class="highlight dart"><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></pre></td><td class="code"><pre><span class="line">Column(</span><br><span class="line"> <span class="comment">// 排除纵轴的默认居中对齐的干扰</span></span><br><span class="line"> crossAxisAlignment: CrossAxisAlignment.start,</span><br><span class="line"> children: <Widget>[</span><br><span class="line"> Row(</span><br><span class="line"> <span class="comment">// RTL.start</span></span><br><span class="line"> mainAxisAlignment: MainAxisAlignment.start,</span><br><span class="line"> textDirection: TextDirection.rtl,</span><br><span class="line"> children: <span class="keyword">const</span> <Widget>[</span><br><span class="line"> Text(<span class="string">" RTL "</span>),</span><br><span class="line"> Text(<span class="string">" 主轴.start "</span>),</span><br><span class="line"> Text(<span class="string">" Hello "</span>),</span><br><span class="line"> Text(<span class="string">" World "</span>),</span><br><span class="line"> ],</span><br><span class="line"> ),</span><br><span class="line"> Row(</span><br><span class="line"> <span class="comment">// LTR.start</span></span><br><span class="line"> mainAxisAlignment: MainAxisAlignment.start,</span><br><span class="line"> textDirection: TextDirection.ltr,</span><br><span class="line"> children: <span class="keyword">const</span> <Widget>[</span><br><span class="line"> Text(<span class="string">" LTR "</span>),</span><br><span class="line"> Text(<span class="string">" 主轴.start "</span>),</span><br><span class="line"> Text(<span class="string">" Hello "</span>),</span><br><span class="line"> Text(<span class="string">" World "</span>),</span><br><span class="line"> ],</span><br><span class="line"> ),</span><br><span class="line"> Container(</span><br><span class="line"> color: Colors.green, <span class="comment">// 设置一个颜色</span></span><br><span class="line"> child: Row(</span><br><span class="line"> <span class="comment">// 宽度为最小值, 对齐无效果</span></span><br><span class="line"> mainAxisSize: MainAxisSize.min,</span><br><span class="line"> mainAxisAlignment: MainAxisAlignment.center,</span><br><span class="line"> children: <span class="keyword">const</span> <Widget>[</span><br><span class="line"> Text(<span class="string">" AxisSize.min "</span>),</span><br><span class="line"> Text(<span class="string">" 主轴.center "</span>),</span><br><span class="line"> Text(<span class="string">" Hello "</span>),</span><br><span class="line"> Text(<span class="string">" World "</span>),</span><br><span class="line"> ],</span><br><span class="line"> ),</span><br><span class="line"> ),</span><br><span class="line"> Container(</span><br><span class="line"> color: Colors.cyan, <span class="comment">// 设置一个颜色</span></span><br><span class="line"> child: Row(</span><br><span class="line"> <span class="comment">// 宽度为最大值, 对齐有效果</span></span><br><span class="line"> mainAxisSize: MainAxisSize.max,</span><br><span class="line"> mainAxisAlignment: MainAxisAlignment.center,</span><br><span class="line"> children: <span class="keyword">const</span> <Widget>[</span><br><span class="line"> Text(<span class="string">" AxisSize.max "</span>),</span><br><span class="line"> Text(<span class="string">" 主轴.center "</span>),</span><br><span class="line"> Text(<span class="string">" Hello "</span>),</span><br><span class="line"> Text(<span class="string">" World "</span>),</span><br><span class="line"> ],</span><br><span class="line"> ),</span><br><span class="line"> ),</span><br><span class="line"> Row(</span><br><span class="line"> <span class="comment">// 纵轴 由下向上布局, 开头对齐</span></span><br><span class="line"> crossAxisAlignment: CrossAxisAlignment.start,</span><br><span class="line"> verticalDirection: VerticalDirection.up,</span><br><span class="line"> children: <span class="keyword">const</span> <Widget>[</span><br><span class="line"> Text(<span class="string">" 纵轴.start "</span>),</span><br><span class="line"> Text(<span class="string">" vertical.up "</span>),</span><br><span class="line"> Text(<span class="string">" Hello "</span>, style: TextStyle(fontSize: <span class="number">30.0</span>)),</span><br><span class="line"> Text(<span class="string">" World "</span>),</span><br><span class="line"> ],</span><br><span class="line"> ),</span><br><span class="line"> Row(</span><br><span class="line"> <span class="comment">// 纵轴 由上向下布局, 开头对齐</span></span><br><span class="line"> crossAxisAlignment: CrossAxisAlignment.start,</span><br><span class="line"> verticalDirection: VerticalDirection.down,</span><br><span class="line"> children: <span class="keyword">const</span> <Widget>[</span><br><span class="line"> Text(<span class="string">" 纵轴.start "</span>),</span><br><span class="line"> Text(<span class="string">" vertical.down "</span>),</span><br><span class="line"> Text(<span class="string">" Hello "</span>, style: TextStyle(fontSize: <span class="number">30.0</span>)),</span><br><span class="line"> Text(<span class="string">" World "</span>),</span><br><span class="line"> ],</span><br><span class="line"> ),</span><br><span class="line"> Row(</span><br><span class="line"> <span class="comment">// 纵轴 由上向下布局, 居中对齐</span></span><br><span class="line"> crossAxisAlignment: CrossAxisAlignment.center,</span><br><span class="line"> verticalDirection: VerticalDirection.down,</span><br><span class="line"> children: <span class="keyword">const</span> <Widget>[</span><br><span class="line"> Text(<span class="string">" 纵轴.center "</span>),</span><br><span class="line"> Text(<span class="string">" vertical.down "</span>),</span><br><span class="line"> Text(<span class="string">" Hello "</span>, style: TextStyle(fontSize: <span class="number">30.0</span>)),</span><br><span class="line"> Text(<span class="string">" World "</span>),</span><br><span class="line"> ],</span><br><span class="line"> ),</span><br><span class="line"> ],</span><br><span class="line">);</span><br></pre></td></tr></table></figure><p>效果</p><img src="/2022/05/25/19cb93b3048e/16535503798437.jpg" class=""><p>如果Row里面嵌套Row,或者Column里面再嵌套Column,那么只有最外面的Row或Column会占用尽可能大的空间,里面Row或Column所占用的空间为实际大小</p><figure class="highlight dart"><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></pre></td><td class="code"><pre><span class="line">Container(</span><br><span class="line"> color: Colors.blue,</span><br><span class="line"> child: Padding(</span><br><span class="line"> padding: <span class="keyword">const</span> EdgeInsets.all(<span class="number">16.0</span>),</span><br><span class="line"> child: Row(</span><br><span class="line"> mainAxisSize: MainAxisSize.max,</span><br><span class="line"> children: <Widget>[</span><br><span class="line"> Container(</span><br><span class="line"> color: Colors.orange,</span><br><span class="line"> child: Row(</span><br><span class="line"> mainAxisSize: MainAxisSize.max,</span><br><span class="line"> children: <span class="keyword">const</span> <Widget>[</span><br><span class="line"> Text(<span class="string">" Hello "</span>),</span><br><span class="line"> Text(<span class="string">" World "</span>),</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"> ),</span><br><span class="line"> ),</span><br><span class="line">);</span><br></pre></td></tr></table></figure><p>效果:</p><img src="/2022/05/25/19cb93b3048e/16535497718012.jpg" class="">]]></content>
<tags>
<tag> iOS </tag>
<tag> Flutter </tag>
<tag> Layout </tag>
</tags>
</entry>
<entry>
<title>LLDB</title>
<link href="/2022/05/24/284708204981.html"/>
<url>/2022/05/24/284708204981.html</url>
<content type="html"><![CDATA[<h1 id="LLDB"><a href="#LLDB" class="headerlink" title="LLDB"></a>LLDB</h1><ul><li><code>po</code>: 为 print object 的缩写,显示对象的文本描述, <code>expression -O</code>的别称</li><li><code>bt</code>: 打印当前堆栈信息</li><li><code>register read xx</code>: 读取寄存器</li><li><code>memory read/个数+格式+每个地址单元的长度 内存地址</code> 查看内存数据<ul><li>默认为:memory read/16xb</li><li><code>格式</code>: x-16进制、f-浮点数,d-10进制,u-10进制无符号,o-8进制,t-2进制<br> a-16进制格式+实际地址类型,i-指令地址格式,c-按字符格式</li><li><code>字节数</code>: b-1个字节,h-2个字节,w-4个字节,g-8个字节。</li><li><code>x = memory read</code> x/16xb</li></ul></li><li><code>memory write 地址 数据</code> 向指定内存写入数据<span id="more"></span>命令格式<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">// 命令 + 子命令 + 命令选项 + 命令参数</span><br><span class="line"><command> [<subcom> [<subcom>...]] <action> [-options [optionvalue]] [arg [arg...]]</span><br></pre></td></tr></table></figure><h2 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h2></li></ul><h3 id="expression"><a href="#expression" class="headerlink" title="expression"></a>expression</h3><p>执行表达式并将表达式的执行结果输出打印。开发中常用po来打印对象,po实际上就是expression -O的别名。</p><h3 id="breakpoint"><a href="#breakpoint" class="headerlink" title="breakpoint"></a>breakpoint</h3><p>代码调试断点</p><h5 id="指定文件和行号设置断点:"><a href="#指定文件和行号设置断点:" class="headerlink" title="指定文件和行号设置断点:"></a>指定文件和行号设置断点:</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">breakpoint set --file easeapi.c --line 12</span><br><span class="line">breakpoint set -f ViewController.m -l 12</span><br></pre></td></tr></table></figure><h5 id="指定函数名称设置断点:"><a href="#指定函数名称设置断点:" class="headerlink" title="指定函数名称设置断点:"></a>指定函数名称设置断点:</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">//对于C函数,填写完整的函数名称。</span><br><span class="line">breakpoint set --name easeapi_func</span><br><span class="line">breakpoint set -n easeapi_func</span><br><span class="line"></span><br><span class="line">//对于Objective-C函数,填写完整的方法签名Selector字符串。</span><br><span class="line">breakpoint set -n viewDidAppear:</span><br><span class="line">breakpoint set -n tableView:cellForRowAtIndexPath:</span><br><span class="line"></span><br><span class="line">//对于Swift方法,填写函数名称,参数省略。</span><br><span class="line">breakpoint set -n easeapi_func</span><br></pre></td></tr></table></figure><h5 id="指定对象方法设置断点:"><a href="#指定对象方法设置断点:" class="headerlink" title="指定对象方法设置断点:"></a>指定对象方法设置断点:</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">breakpoint set -n "-[ViewController viewDidAppear:]"</span><br><span class="line">breakpoint set -n "+[ViewController classFunc]"</span><br><span class="line">//Swift函数</span><br><span class="line">breakpoint set -n "ViewController.easeapi_func"</span><br></pre></td></tr></table></figure><h5 id="指定代码地址设置断点:"><a href="#指定代码地址设置断点:" class="headerlink" title="指定代码地址设置断点:"></a>指定代码地址设置断点:</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">breakpoint set --address 0x1021744bb</span><br><span class="line">breakpoint set -a 0x1021744bb</span><br></pre></td></tr></table></figure><h5 id="查看已设置的断点"><a href="#查看已设置的断点" class="headerlink" title="查看已设置的断点"></a>查看已设置的断点</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">breakpoint list</span><br></pre></td></tr></table></figure><p>每一次设置的断点都是逻辑断点(对应编号1、2、3等),一个逻辑断点可以解析为多个断点位置(对应编号1.1等)</p><h5 id="取消断点"><a href="#取消断点" class="headerlink" title="取消断点"></a>取消断点</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">breakpoint delete 断点编号</span><br></pre></td></tr></table></figure><p>若不加编号则为所有断点</p><h4 id="watchpoint"><a href="#watchpoint" class="headerlink" title="watchpoint"></a>watchpoint</h4><p>内存调试断点</p><h5 id="设置观察变量:"><a href="#设置观察变量:" class="headerlink" title="设置观察变量:"></a>设置观察变量:</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">watchpoint set variable value</span><br><span class="line">watchpoint set variable self->_dataArray //不能使用点语法</span><br></pre></td></tr></table></figure><h5 id="设置观察内存地址:"><a href="#设置观察内存地址:" class="headerlink" title="设置观察内存地址:"></a>设置观察内存地址:</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">watchpoint set expression 0x000000016f47fc70</span><br></pre></td></tr></table></figure><h5 id="查看所有内存断点:"><a href="#查看所有内存断点:" class="headerlink" title="查看所有内存断点:"></a>查看所有内存断点:</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">watchpoint list</span><br></pre></td></tr></table></figure><h5 id="删除内存断点:"><a href="#删除内存断点:" class="headerlink" title="删除内存断点:"></a>删除内存断点:</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">watchpoint delete index</span><br><span class="line">watchpoint delete</span><br></pre></td></tr></table></figure><h3 id="register"><a href="#register" class="headerlink" title="register"></a>register</h3><p>寄存器操作</p><p><code>register read</code> 读取所有寄存器<br>ARM64架构中共有34个寄存器,包括31个通用寄存器、SP、PC、CPSR。</p><ul><li>通用寄存器<ul><li>r0 - r30是31个通用寄存器,每个寄存器可以存取一个64位大小的数。 </li><li>当使用x0 - x30访问时,它就是一个64位的数。</li><li>当使用w0 - w30访问时,是这些寄存器的低32位。 </li><li>r29又称FP寄存器(frame point),主要用来保存栈帧(栈底)指针。 </li><li>r30又称LR寄存器(link register),主要用来保存函数返回地址。</li></ul></li><li>SP:stack pointer,栈顶指针;</li><li>PC:用来记录当前执行的指令地址;</li><li>CPSR:状态寄存器。</li></ul><p>读取指定寄存器的值:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">register read x1</span><br></pre></td></tr></table></figure><p>写入寄存器:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">register write x0 1</span><br></pre></td></tr></table></figure><h3 id="memory"><a href="#memory" class="headerlink" title="memory"></a>memory</h3><p>内存操作</p><h4 id="从内存读取数据"><a href="#从内存读取数据" class="headerlink" title="从内存读取数据"></a>从内存读取数据</h4><p><code>memory read/个数+格式+每个地址单元的长度 内存地址</code></p><ul><li>默认为:memory read/16xb</li><li><code>格式</code>: x-16进制、f-浮点数,d-10进制,u-10进制无符号,o-8进制,t-2进制;<br> a-16进制格式+实际地址类型,i-指令地址格式,c-按字符格式</li><li><code>字节数</code>: b-1个字节,h-2个字节,w-4个字节,g-8个字节。</li></ul><p>等价于 <code>x/16xb = memory read/16xb</code></p><h4 id="往内存写入数据"><a href="#往内存写入数据" class="headerlink" title="往内存写入数据"></a>往内存写入数据</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">memory write 地址 数据</span><br><span class="line">//以8字节对齐,写入两个数据</span><br><span class="line">memory write 0x000000016f08fc70 -s 8 0x01 0x02</span><br></pre></td></tr></table></figure><h3 id="image"><a href="#image" class="headerlink" title="image"></a>image</h3><p>image镜像文件操作</p><p>查看已经加载的Image</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">image list</span><br></pre></td></tr></table></figure><p>查看信息</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">//查找类信息</span><br><span class="line">image lookup --type UIViewController</span><br><span class="line">image lookup -t UIViewController</span><br><span class="line">//查找符号</span><br><span class="line">image lookup --name viewDidLoad</span><br><span class="line">image lookup -n viewDidLoad</span><br><span class="line">//查找地址</span><br><span class="line">image lookup --address 0x000000018ff60490</span><br><span class="line">image lookup -a 0x000000018ff60490</span><br></pre></td></tr></table></figure><p>导出image信息:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">//导出所有sections信息</span><br><span class="line">image dump sections</span><br><span class="line">//导出所有符号信息</span><br><span class="line">image dump symtab</span><br></pre></td></tr></table></figure><h3 id="thread"><a href="#thread" class="headerlink" title="thread"></a>thread</h3><p>线程操作</p><p>查看线程列表<br><code>thread list</code><br>其中,使用*标记当前线程;使用#标记线程编号。</p><p>获取线程调用栈:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">//获取当前线程调用栈</span><br><span class="line">thread backtrace</span><br><span class="line">//函数的堆栈</span><br><span class="line">bt</span><br><span class="line">//获取所有线程调用栈</span><br><span class="line">thread backtrace all</span><br></pre></td></tr></table></figure><p>在Xcode中,有四个控制Debug的按钮:</p><ul><li>Continue:程序继续运行<br> <code>thread continue/continue/c</code></li><li>Step over:单步指定,遇到子函数时断点不会进入子函数。<br> <code>thread step-over/next/n</code></li><li>Step into:单步运行,遇到子函数时断点会进入子函数。<br> <code>thread step-into/step/s</code></li><li>Step out:执行完当前函数剩余的代码,返回上一层函数。<br> <code>thread step-out/finish</code></li></ul><p>修改函数返回:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">thread return 10</span><br></pre></td></tr></table></figure><h3 id="frame"><a href="#frame" class="headerlink" title="frame"></a>frame</h3><p>栈帧信息<br>查看当前栈帧变量:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">frame variable</span><br></pre></td></tr></table></figure><h3 id="disassemble"><a href="#disassemble" class="headerlink" title="disassemble"></a>disassemble</h3><p>显示汇编代码<br>使用d/di/dis同等效果。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">disassemble -b</span><br><span class="line">disassemble --frame</span><br><span class="line">disassemble --name func_name</span><br><span class="line">disassemble -a address</span><br><span class="line">disassemble -s address</span><br></pre></td></tr></table></figure>]]></content>
<tags>
<tag> Xcode </tag>
<tag> iOS </tag>
<tag> LLDB </tag>
</tags>
</entry>
<entry>
<title>Flutter 布局约束</title>
<link href="/2022/05/24/11406298780d.html"/>
<url>/2022/05/24/11406298780d.html</url>
<content type="html"><![CDATA[<h1 id="布局约束"><a href="#布局约束" class="headerlink" title="布局约束"></a>布局约束</h1><p>Flutter 中有两种布局模型:</p><ul><li>基于 RenderBox 的盒模型布局。</li><li>基于 Sliver ( RenderSliver ) 按需加载列表布局。</li></ul><p>大致布局流程如下:</p><ol><li>上层组件向下层组件传递约束(constraints)条件。</li><li>下层组件确定自己的大小,然后告诉上层组件。注意下层组件的大小必须符合父组件的约束。</li><li>上层组件确定下层组件相对于自身的偏移和确定自身的大小(大多数情况下会根据子组件的大小来确定自身的大小)。</li></ol><p><code>因为任何时候子组件都必须先遵守父组件的约束</code></p><span id="more"></span><p>盒模型布局组件有两个特点:</p><ol><li>组件对应的渲染对象都继承自 RenderBox 类。在本书后面文章中如果提到某个组件是 RenderBox,则指它是基于盒模型布局的,而不是说组件是 RenderBox 类的实例。</li><li>在布局过程中父级传递给子级的约束信息由 BoxConstraints 描述。</li></ol><h3 id="BoxConstraints-父-gt-子-的约束信息"><a href="#BoxConstraints-父-gt-子-的约束信息" class="headerlink" title="BoxConstraints (父->子)的约束信息"></a>BoxConstraints (父->子)的约束信息</h3><figure class="highlight dart"><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="keyword">const</span> BoxConstraints({</span><br><span class="line"> <span class="keyword">this</span>.minWidth = <span class="number">0.0</span>, <span class="comment">//最小宽度</span></span><br><span class="line"> <span class="keyword">this</span>.maxWidth = <span class="built_in">double</span>.infinity, <span class="comment">//最大宽度</span></span><br><span class="line"> <span class="keyword">this</span>.minHeight = <span class="number">0.0</span>, <span class="comment">//最小高度</span></span><br><span class="line"> <span class="keyword">this</span>.maxHeight = <span class="built_in">double</span>.infinity <span class="comment">//最大高度</span></span><br><span class="line">})</span><br></pre></td></tr></table></figure><p>BoxConstraints.tight(Size size),它可以生成固定宽高的限制;<br>BoxConstraints.expand()可以生成一个尽可能大的用以填充另一个容器的BoxConstraints;</p><h3 id="ConstrainedBox"><a href="#ConstrainedBox" class="headerlink" title="ConstrainedBox"></a>ConstrainedBox</h3><p>通过约束限制子组件大小的组件</p><figure class="highlight dart"><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">Widget yellowBox = <span class="keyword">const</span> DecoratedBox(</span><br><span class="line"> decoration: BoxDecoration(color: Colors.yellow),</span><br><span class="line">);</span><br></pre></td></tr></table></figure><figure class="highlight dart"><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">Widget testConstrainedBox() {</span><br><span class="line"> <span class="keyword">return</span> ConstrainedBox( <span class="comment">// 父组件</span></span><br><span class="line"> constraints: <span class="keyword">const</span> BoxConstraints( <span class="comment">// 父组件对子组件的 约束信息</span></span><br><span class="line"> minWidth: <span class="built_in">double</span>.infinity, <span class="comment">// 宽度尽可能大</span></span><br><span class="line"> minHeight: <span class="number">80.0</span> <span class="comment">// 最小高度为80像素</span></span><br><span class="line"> ),</span><br><span class="line"> child: SizedBox( <span class="comment">// 子组件</span></span><br><span class="line"> height: <span class="number">20.0</span>, <span class="comment">// 虽然20小于80, 但是父组件约束了最小为80</span></span><br><span class="line"> child: yellowBox,</span><br><span class="line"> ),</span><br><span class="line"> );</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>效果</p><img src="/2022/05/24/11406298780d/16533793465334.jpg" class=""> <p>虽然自组件设置的高是20, 但是父组件约束了最小为80, 所以高度是80</p><h4 id="SizedBox"><a href="#SizedBox" class="headerlink" title="SizedBox"></a>SizedBox</h4><p>SizedBox只是ConstrainedBox的一个定制,</p><figure class="highlight dart"><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">SizedBox(width: <span class="number">80.0</span>, height: <span class="number">80.0</span>, child: yellowBox)</span><br><span class="line"><span class="comment">// 等价于 </span></span><br><span class="line">ConstrainedBox(</span><br><span class="line"> constraints: BoxConstraints.tightFor(width: <span class="number">80.0</span>, height: <span class="number">80.0</span>),</span><br><span class="line"> child: yellowBox, </span><br><span class="line">)</span><br><span class="line"><span class="comment">// 又等价于</span></span><br><span class="line">ConstrainedBox(</span><br><span class="line"> constraints: BoxConstraints(minHeight: <span class="number">80.0</span>, maxHeight: <span class="number">80.0</span>, minWidth: <span class="number">80.0</span>, maxWidth: <span class="number">80.0</span>),</span><br><span class="line"> child: yellowBox, </span><br><span class="line">)</span><br></pre></td></tr></table></figure><img src="/2022/05/24/11406298780d/16533795446838.jpg" class=""><p>其实<code>ConstrainedBox</code>和<code>SizedBox</code>都是通过<code>RenderConstrainedBox</code>来渲染的;</p><h4 id="多层约束"><a href="#多层约束" class="headerlink" title="多层约束"></a>多层约束</h4><p>如果使用多层ConstrainedBox父组件 会是什么情况呢?</p><figure class="highlight dart"><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="comment">// 外小 内大</span></span><br><span class="line">ConstrainedBox( <span class="comment">// 祖父组件</span></span><br><span class="line"> constraints: BoxConstraints(minWidth: <span class="number">140.0</span>, minHeight: <span class="number">40.0</span>),</span><br><span class="line"> child: ConstrainedBox( <span class="comment">// 父组件</span></span><br><span class="line"> constraints: BoxConstraints(minWidth: <span class="number">180.0</span>, minHeight: <span class="number">80.0</span>),</span><br><span class="line"> child: yellowBox, <span class="comment">// 子组件</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">ConstrainedBox( <span class="comment">// 祖父组件</span></span><br><span class="line"> constraints: BoxConstraints(minWidth: <span class="number">180.0</span>, minHeight: <span class="number">80.0</span>),</span><br><span class="line"> child: ConstrainedBox( <span class="comment">// 父组件</span></span><br><span class="line"> constraints: BoxConstraints(minWidth: <span class="number">140.0</span>, minHeight: <span class="number">40.0</span>),</span><br><span class="line"> child: yellowBox, <span class="comment">// 子组件</span></span><br><span class="line"> ),</span><br><span class="line">);</span><br></pre></td></tr></table></figure><img src="/2022/05/24/11406298780d/16533807548379.jpg" class=""><p>因为约束条件是用来约束子组件的</p><ul><li>一层约束时很好理解, 即: <code>maxSize >= 最终大小 && 最终大小 >= minSize</code></li><li>那两层也不难理解, 只要两层约束条件都满足即可: <figure class="highlight dart"><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">// maxSize1 >= 最终大小 && 最终大小 >= minSize1</span></span><br><span class="line"><span class="comment">// &&</span></span><br><span class="line"><span class="comment">// maxSize2 >= 最终大小 && 最终大小 >= minSize2</span></span><br><span class="line"><span class="comment">// 整理即可得出 </span></span><br><span class="line"><span class="comment">// min(maxSize1, maxSize2) >= 最终大小 >= max(minSize1, minSize2)</span></span><br></pre></td></tr></table></figure></li></ul><h3 id="UnconstrainedBox"><a href="#UnconstrainedBox" class="headerlink" title="UnconstrainedBox"></a>UnconstrainedBox</h3><p>虽然任何时候子组件都必须遵守其父组件的约束,但前提条件是它们必须是父子关系,</p><figure class="highlight dart"><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">ConstrainedBox( <span class="comment">// 曾祖父组件</span></span><br><span class="line"> constraints: BoxConstraints(minWidth: <span class="number">180.0</span>, minHeight: <span class="number">80.0</span>), <span class="comment">// 曾祖父组件约束</span></span><br><span class="line"> child: UnconstrainedBox( <span class="comment">// 祖父组件, “去除”曾祖父组件的约束</span></span><br><span class="line"> child: ConstrainedBox( <span class="comment">// 父组件</span></span><br><span class="line"> constraints: BoxConstraints(minWidth: <span class="number">80.0</span>, minHeight: <span class="number">30.0</span>), <span class="comment">// 父组件约束</span></span><br><span class="line"> child: yellowBox, <span class="comment">// 子组件</span></span><br><span class="line"> ),</span><br><span class="line"> ),</span><br><span class="line">);</span><br></pre></td></tr></table></figure><img src="/2022/05/24/11406298780d/16533826173981.jpg" class=""><p><strong>任何时候子组件都必须遵守其父组件的约束</strong></p><p>需要注意,UnconstrainedBox 虽然在其子组件布局时可以取消约束(子组件可以为无限大),但是 UnconstrainedBox 自身是受其父组件约束的,所以当 UnconstrainedBox 随着其子组件变大后,如果UnconstrainedBox 的大小超过它父组件约束时,也会导致溢出报错!</p><h3 id="其他约束类"><a href="#其他约束类" class="headerlink" title="其他约束类"></a>其他约束类</h3><p>还有一些其他的尺寸限制类容器</p><ul><li><code>AspectRatio</code> 它可以指定子组件的长宽比、</li><li><code>LimitedBox</code> 用于指定最大宽高、</li><li><code>FractionallySizedBox</code> 可以根据父容器宽高的百分比来设置子组件宽高等</li></ul>]]></content>
<tags>
<tag> iOS </tag>
<tag> Flutter </tag>
<tag> Layout </tag>
</tags>
</entry>
<entry>
<title>复习GCD</title>
<link href="/2022/05/23/be08fa8a65d5.html"/>
<url>/2022/05/23/be08fa8a65d5.html</url>
<content type="html"><![CDATA[<h2 id="队列-FIFO"><a href="#队列-FIFO" class="headerlink" title="队列 FIFO"></a>队列 FIFO</h2><ul><li>串行队列</li><li>并发队列</li><li>全局并发队列</li><li>主队列</li></ul><p>队列只是用来存储任务,没有能力去调度任务</p><span id="more"></span><h2 id="任务"><a href="#任务" class="headerlink" title="任务"></a>任务</h2><ul><li>同步任务 dispatch_sync<ul><li>立即执行、会阻塞当前线程、不具备开辟子线程的能力</li><li>没有线程相关的操作、没有保存任务、立即执行了任务</li></ul></li><li>异步任务 dispatch_async<ul><li>开辟子线程、不会立即执行、不会阻塞当前线程</li><li>保存block、函数式编程、有线程相关的操作</li></ul></li></ul><p>死锁: 在当前线程同步的向串行队列里面添加任务,当前线程锁执行的任务是从当前队列里取出来的</p>]]></content>
<tags>
<tag> iOS </tag>
<tag> GCD </tag>
</tags>
</entry>
<entry>
<title>编译Objc4-838</title>
<link href="/2022/05/08/e233db870454.html"/>
<url>/2022/05/08/e233db870454.html</url>
<content type="html"><![CDATA[<h1 id="编译Objc源码"><a href="#编译Objc源码" class="headerlink" title="编译Objc源码"></a>编译Objc源码</h1><p>要诀:<br>能删则删, 不确定先注释,<br>需加须加, 能设置就设置.</p><h1 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h1><p>本次编译<code>objc4-838</code>源码, 即对应<code>macOS 12.2</code>, 高版本未尝试, 理论上大版本一致可行<br>以下相关源码均可在<a href="https://opensource.apple.com/releases/">Apple Open Source</a>中 <code>macOS Monterey 12 -> macOS 12.2</code> 分支看到</p><span id="more"></span><p><a href="https://github.com/apple-oss-distributions/objc4/archive/objc4-838.1.tar.gz">objc4-838 下载地址</a> </p><p><a href="https://github.com/apple-oss-distributions/dyld/archive/dyld-941.5.tar.gz">dyld-941.5 下载地址</a></p><p><a href="https://github.com/apple-oss-distributions/Libc/archive/Libc-1506.40.4.tar.gz">Libc-1506.40.4 下载地址</a></p><p><a href="https://github.com/apple-oss-distributions/libclosure/archive/libclosure-79.tar.gz">libclosure-79 下载地址</a></p><p><a href="https://github.com/apple-oss-distributions/libplatform/archive/libplatform-273.40.1.tar.gz">libplatform-273.40.1 下载地址</a></p><p><a href="https://github.com/apple-oss-distributions/libpthread/archive/libpthread-485.60.2.tar.gz">libpthread-485.60.2 下载地址</a></p><p><a href="https://github.com/apple-oss-distributions/xnu/archive/xnu-8019.80.24.tar.gz">xnu-8019.80.24 下载地址</a></p><p>旧版源码下载<br><a href="https://github.com/apple-oss-distributions/Libc/archive/Libc-825.26.tar.gz">Libc-825.26 下载地址</a> 在 <code>OS X Mountain Lion 10.8 -> Mac OS X 10.8.4</code> 分支下</p><p><a href="https://github.com/apple-oss-distributions/libplatform/archive/libplatform-220.100.1.tar.gz">libplatform-220.100.1 下载地址</a>在 <code>macOS Catalina 10.15 -> macOS 10.15.6</code> 分支下</p><h1 id="Project-相关"><a href="#Project-相关" class="headerlink" title="Project 相关"></a>Project 相关</h1><h2 id="修改-Base-SDK"><a href="#修改-Base-SDK" class="headerlink" title="修改 Base SDK"></a>修改 Base SDK</h2><p>在 <code>Project -> Build Setting -> Base SDK</code> 选择为<code>macOS</code></p><img src="/2022/05/08/e233db870454/16520180096055.jpg" class=""><h2 id="选择编译-Targets-为-objc"><a href="#选择编译-Targets-为-objc" class="headerlink" title="选择编译 Targets 为 objc"></a>选择编译 Targets 为 objc</h2><img src="/2022/05/08/e233db870454/16520180485207.jpg" class=""><h1 id="Targets-配置相关"><a href="#Targets-配置相关" class="headerlink" title="Targets 配置相关"></a>Targets 配置相关</h1><h2 id="修改-Script"><a href="#修改-Script" class="headerlink" title="修改 Script"></a>修改 Script</h2><p>在 <code>Targets -> objc -> Build Phases -> Run Script (markgc)</code> 将 <code>macosx.internal</code> 改成 <code>macosx</code></p><img src="/2022/05/08/e233db870454/16520182953780.jpg" class=""><h2 id="编译时-报错"><a href="#编译时-报错" class="headerlink" title="编译时 报错"></a>编译时 报错</h2><p>文件缺失居多, <code>xx file not found</code></p><p>在项目根目录新增一目录, 用来放缺失文件, (名字可以自定义, 比如<code>/common</code>)<br>然后在项目 <code>Targets -> Build Settings -> Header Search Paths</code> 新增 <code>/common</code> 路径:<code>$(SRCROOT)/common</code></p><img src="/2022/05/08/e233db870454/16520025810206.jpg" class=""><ol><li><p><code>'sys/reason.h' file not found</code><br>在<code>xnu</code>源码的<code>/bsd/sys/reason.h</code>目录下载文件<code>reason.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/sys/reason.h</code>目录</p><img src="/2022/05/08/e233db870454/16520057299390.jpg" class=""></li><li><p><code>'os/feature_private.h' file not found</code><br>直接注释即可, 共三处, 其<code>NSObject.mm</code>有两处</p><img src="/2022/05/08/e233db870454/16520190168277.jpg" class=""></li><li><p><code>'mach-o/dyld_priv.h' file not found</code><br>在<code>dyld</code>源码的<code>/include/mach-o/dyld_priv.h</code>目录下载文件<code>dyld_priv.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/mach-o/dyld_priv.h</code>目录</p><img src="/2022/05/08/e233db870454/16520057504672.jpg" class=""><p>然后要此文件添加宏定义:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">#define DYLD_MACOSX_VERSION_10_11 0x000A0B00</span><br><span class="line">#define DYLD_MACOSX_VERSION_10_12 0x000A0C00</span><br><span class="line">#define DYLD_MACOSX_VERSION_10_13 0x000A0D00</span><br><span class="line">#define DYLD_MACOSX_VERSION_10_14 0x000A0E00</span><br></pre></td></tr></table></figure></li><li><p><code>Expected ','</code> 在 <code>/mach-o/dyld_priv.h</code> 文件中<br>移除<code>__API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0), bridgeos(3.0))</code> 中 <code>bridgeos(3.0)</code> 的条件即可</p><img src="/2022/05/08/e233db870454/16520197415089.jpg" class=""></li><li><p><code>'os/lock_private.h' file not found</code><br>在<code>libplatform</code>源码的<code>/private/os/lock_private.h</code>目录下载文件<code>lock_private.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/os/lock_private.h</code>目录</p><img src="/2022/05/08/e233db870454/16520057891584.jpg" class=""></li><li><p><code>Expected ','</code> 在 <code>/os/lock_private.h</code> 文件中<br>移除<code>__API_AVAILABLE(macos(10.15), ios(13.0), tvos(13.0), watchos(6.0), bridgeos(4.0))</code> 中 <code>bridgeos(4.0)</code> 的条件即可</p><img src="/2022/05/08/e233db870454/16520202025735.jpg" class=""></li><li><p><code>'os/base_private.h' file not found</code><br>在<code>libplatform-220.100.1</code>源码的<code>/private/os/base_private.h</code>目录下载文件<code>base_private.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/os/base_private.h</code>目录</p><img src="/2022/05/08/e233db870454/16520159895858.jpg" class=""></li><li><p><code>'pthread/tsd_private.h' file not found</code><br>在<code>libpthread</code>源码的<code>/private/pthread/tsd_private.h</code>目录下载文件<code>tsd_private.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/pthread/tsd_private.h</code>目录</p><img src="/2022/05/08/e233db870454/16520160082926.jpg" class=""></li><li><p><code>'System/machine/cpu_capabilities.h' file not found</code><br>在<code>xnu</code>源码的<code>/osfmk/machine/cpu_capabilities.h</code>目录下载文件<code>cpu_capabilities.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/System/machine/cpu_capabilities.h</code>目录</p><img src="/2022/05/08/e233db870454/16520160595511.jpg" class=""></li><li><p><code>'os/tsd.h' file not found</code><br>在<code>xnu</code>源码的<code>libsyscall/os/tsd.h</code>目录下载文件<code>tsd.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/os/tsd.h</code>目录</p><img src="/2022/05/08/e233db870454/16520160761343.jpg" class=""></li><li><p><code>'pthread/spinlock_private.h' file not found</code><br>在<code>libpthread</code>源码的<code>/private/pthread/spinlock_private.h</code>目录下载文件<code>spinlock_private.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/pthread/spinlock_private.h</code>目录</p><img src="/2022/05/08/e233db870454/16520161190991.jpg" class=""></li><li><p><code>'System/pthread_machdep.h' file not found</code><br>在<code>Libc-825.26</code>源码的<code>/pthreads/pthread_machdep.h</code>目录下载文件<code>pthread_machdep.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/System/pthread_machdep.h</code>目录</p><img src="/2022/05/08/e233db870454/16520161567520.jpg" class=""></li><li><p><code>'CrashReporterClient.h' file not found</code></p></li></ol><ul><li><p>在<code>Libc-825.26</code>源码的<code>/include/CrashReporterClient.h</code>目录下载文件<code>CrashReporterClient.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/CrashReporterClient.h</code>目录</p> <img src="/2022/05/08/e233db870454/16520161828314.jpg" class=""></li><li><p>还未结束, 因为还缺少宏定义, 在 <code>Targets -> objc -> Build Settings -> Preprocessor Macros</code> 中,添加<code>LIBC_NO_LIBCRASHREPORTERCLIENT</code></p> <img src="/2022/05/08/e233db870454/16520040737366.jpg" class=""></li></ul><ol start="14"><li>在 <code>pthread_machdep.h</code> 文件中一个typedef和三个函数, 这些全部注释即可</li></ol><ul><li><p><code>Typedef redefinition with different types ('int' vs 'volatile OSSpinLock' (aka 'volatile int'))</code></p><img src="/2022/05/08/e233db870454/16520210232107.jpg" class=""></li><li><p><code>Static declaration of '_pthread_has_direct_tsd' follows non-static declaration</code></p><img src="/2022/05/08/e233db870454/16520210499881.jpg" class=""></li><li><p><code>Static declaration of '_pthread_getspecific_direct' follows non-static declaration</code></p><img src="/2022/05/08/e233db870454/16520210663906.jpg" class=""></li><li><p><code>Static declaration of '_pthread_setspecific_direct' follows non-static declaration</code></p><img src="/2022/05/08/e233db870454/16520210870245.jpg" class=""></li></ul><ol start="15"><li><p><code>Unknown type name 'uint32_t' 'uint64_t, Use of undeclared identifier 'INT64_C'</code> 在 <code>/llvm-MathExtras.h</code> 文件中<br>导入头文件 <code>#include <cstdint></code> 即可解决</p><img src="/2022/05/08/e233db870454/16520218944361.jpg" class=""></li><li><p><code>Use of undeclared identifier 'dyld_fall_2020_os_versions'</code></p><img src="/2022/05/08/e233db870454/16520219604415.jpg" class=""></li><li><p><code>Use of undeclared identifier 'objc4' 'preoptimizedCaches'</code></p><img src="/2022/05/08/e233db870454/16520220277190.jpg" class=""></li><li><p><code>'objc-shared-cache.h' file not found</code><br>在<code>dyld</code>源码的<code>/include/objc-shared-cache.h</code>目录下载文件<code>objc-shared-cache.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/objc-shared-cache.h</code>目录</p><img src="/2022/05/08/e233db870454/16520162251666.jpg" class=""></li><li><p><code>Use of undeclared identifier 'dyld_platform_version_macOS_10_13'</code></p><img src="/2022/05/08/e233db870454/16520223502584.jpg" class=""></li><li><p><code>Use of undeclared identifier 'dyld_platform_version_macOS_10_11'</code></p><img src="/2022/05/08/e233db870454/16520222826801.jpg" class=""></li><li><p><code>Use of undeclared identifier 'dyld_fall_2018_os_versions'</code> 注释部分判断条件</p><img src="/2022/05/08/e233db870454/16520223139195.jpg" class=""></li><li><p><code>'Block_private.h' file not found</code><br>在<code>libclosure</code>源码的<code>/Block_private.h</code>目录下载文件<code>Block_private.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/Block_private.h</code>目录</p><img src="/2022/05/08/e233db870454/16520163360611.jpg" class=""></li><li><p><code>'Cambria/Traps.h' file not found</code><br>直接注释即可</p><figure class="highlight c"><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="comment">// #include <Cambria/Traps.h></span></span><br><span class="line"><span class="comment">// #include <Cambria/Cambria.h></span></span><br></pre></td></tr></table></figure></li><li><p><code>'_simple.h' file not found</code><br>在<code>libplatform</code>源码的<code>/private/_simple.h</code>目录下载文件<code>_simple.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/_simple.h</code>目录</p><img src="/2022/05/08/e233db870454/16520162431797.jpg" class=""></li><li><p><code>'os/linker_set.h' file not found</code><br>在<code>xnu</code>源码的<code>/bsd/sys/linker_set.h</code>目录下载文件<code>linker_set.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/os/linker_set.h</code>目录</p><img src="/2022/05/08/e233db870454/16520227164945.jpg" class=""></li><li><p><code>'kern/restartable.h' file not found</code><br>在<code>xnu</code>源码的<code>/osfmk/kern/restartable.h</code>目录下载文件<code>restartable.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/kern/restartable.h</code>目录</p><img src="/2022/05/08/e233db870454/16520164250072.jpg" class=""></li><li><p><code>Use of undeclared identifier 'oah_is_current_process_translated' 和 'objc_thread_get_rip'</code> 注释此<code>if</code>分支</p><img src="/2022/05/08/e233db870454/16520228608250.jpg" class=""></li><li><p><code>'os/reason_private.h' file not found</code><br>在<code>xnu</code>源码的<code>/libkern/os/reason_private.h</code>目录下载文件<code>reason_private.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/os/reason_private.h</code>目录</p><img src="/2022/05/08/e233db870454/16520231987128.jpg" class=""></li><li><p><code>'os/variant_private.h' file not found</code><br>在<code>Libc</code>源码的<code>/os/variant_private.h</code>目录下载文件<code>variant_private.h</code>文件, 拷贝至<code>/common</code>下, 对应<code>/os/variant_private.h</code>目录</p><img src="/2022/05/08/e233db870454/16520232315070.jpg" class=""><p>还要去掉文件里面的 <code>bridgeos 、 bridgeos(4.0)</code> 参数</p></li><li><p><code>Use of undeclared identifier 'dyld_platform_version_bridgeOS_2_0' iOS_10_0 macOS_10_12 tvOS_10_0 watchOS_3_0</code> 注释此<code>if</code>判断</p><img src="/2022/05/08/e233db870454/16520234982550.jpg" class=""></li><li><p><code>'_static_assert' declared as an array with a negative size</code></p><img src="/2022/05/08/e233db870454/16520235358635.jpg" class=""></li></ol><h2 id="链接时-报错"><a href="#链接时-报错" class="headerlink" title="链接时 报错"></a>链接时 报错</h2><ul><li><p><code>Library not found for -lCrashReporterClient</code><br>进入 <code>Targets -> objc -> Build Setting -> Other Linker Flags</code> 中,删除 <code>-lCrashReporterClient</code></p></li><li><p><code>Library not found for -loah</code><br>进入 <code>Targets -> objc -> Build Setting -> Other Linker Flags</code> 中,删除 <code>-loah</code></p></li></ul><h1 id="终于-Build-Succeded"><a href="#终于-Build-Succeded" class="headerlink" title="终于 Build Succeded"></a>终于 <code>Build Succeded</code></h1><img src="/2022/05/08/e233db870454/16520238050066.jpg" class=""><h1 id="添加测试-Target"><a href="#添加测试-Target" class="headerlink" title="添加测试 Target"></a>添加测试 <code>Target</code></h1><ol><li><p>新增Target<br>点击在 <code>Target</code> 左下角的 <code>+</code>, 然后选择 <code>macOS -> Command Line Tool</code>, 随便取名, 比如<code>TestOC</code></p><img src="/2022/05/08/e233db870454/16520245571391.jpg" class=""></li><li><p>链接<code>libobjc.A.dylib</code><br>选择 <code>Target -> TestOC -> General -> Frameworks and Libraries</code> 的 <code>+</code> 然后选择 <code>libobjc.A.dylib</code> 点击 <code>Add</code></p><img src="/2022/05/08/e233db870454/16520245370237.jpg" class=""></li></ol><h1 id="编译-TestOC-Target"><a href="#编译-TestOC-Target" class="headerlink" title="编译 TestOC Target"></a>编译 TestOC Target</h1><ol><li><p>选择新 Target - TestOC</p><img src="/2022/05/08/e233db870454/16520247646137.jpg" class=""></li><li><p>愉快的在main中写代码吧</p><img src="/2022/05/08/e233db870454/16520250796382.jpg" class=""></li><li><p>此时可能会发现, 断点发虚, 无法触发</p><img src="/2022/05/08/e233db870454/16520252735294.jpg" class=""><p> 断点失败, 解决方法有二</p><ul><li>第一种: 关闭LTO(<code>Link-Time Optimization</code>),<br> 找到<code>Targets -> Build Settings -> Link-Time Optimization</code>, 选择值为 <code>NO</code> 即可<br> LTO 代码链接时候的一个优化选项, Apple官方解释: <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Enabling this setting allows optimization across file boundaries during linking. </span><br><span class="line">**No:* </span><br><span class="line">Disabled. Do not use link-time optimization. </span><br><span class="line">**Monolithic Link-Time Optimization:*</span><br><span class="line">This mode performs monolithic link-time optimization of binaries, combining all executable code into a single unit and running aggressive compiler optimizations.</span><br><span class="line">**Incremental Link-Time Optimization:* </span><br><span class="line">This mode performs partitioned link-time optimization of binaries, inlining between compilation units and running aggressive compiler optimizations on each unit in parallel. This enables fast incremental builds and uses less memory than Monolithic LTO.</span><br></pre></td></tr></table></figure></li><li>第二种:<ol><li>找到 <code>Build Phases -> Compile Sources</code> 中,确保 <code>main.m</code> 在最最最前面</li><li>找到 <code>Targets -> Build Settings -> Enable Hardened Runtime</code> ,确保值为 <code>NO</code></li></ol></li></ul></li></ol>]]></content>
<tags>
<tag> Xcode </tag>
<tag> iOS </tag>
<tag> objc </tag>
</tags>
</entry>
<entry>
<title>macOS 使用SFMono字体</title>
<link href="/2019/08/29/3504b9da5c42.html"/>
<url>/2019/08/29/3504b9da5c42.html</url>
<content type="html"><![CDATA[<h3 id="从-macOS-中提取-SF-Mono-字体"><a href="#从-macOS-中提取-SF-Mono-字体" class="headerlink" title="从 macOS 中提取 SF Mono 字体"></a>从 macOS 中提取 SF Mono 字体</h3><h6 id="在-终端-中提取-SF-Mono-字体完整路径为:"><a href="#在-终端-中提取-SF-Mono-字体完整路径为:" class="headerlink" title="在 终端 中提取 SF Mono 字体完整路径为:"></a>在 终端 中提取 SF Mono 字体完整路径为:</h6><p><code>/Applications/Utilities/Terminal.app/Contents/Resources/Fonts/</code></p><h6 id="在-Xcode-中提取-SF-Mono-字体完整路径为:"><a href="#在-Xcode-中提取-SF-Mono-字体完整路径为:" class="headerlink" title="在 Xcode 中提取 SF Mono 字体完整路径为:"></a>在 Xcode 中提取 SF Mono 字体完整路径为:</h6><p><code>/Applications/Xcode.app/Contents/SharedFrameworks/DVTKit.framework/Versions/A/Resources/Fonts</code></p><span id="more"></span><h3 id="安装到系统。"><a href="#安装到系统。" class="headerlink" title="安装到系统。"></a>安装到系统。</h3><h6 id="通过-访达-安装"><a href="#通过-访达-安装" class="headerlink" title="通过 访达 安装"></a>通过 访达 安装</h6><p>在访达中通过路径前往文件夹鼠标操作:<code>菜单栏-->前往-->前往文件夹</code>;快捷键操作:<code>⇧+⌘+G</code>。然后输入上面的路径前往,然后全选所有字体文件,双击安装。</p><h6 id="通过-终端-命令行安装"><a href="#通过-终端-命令行安装" class="headerlink" title="通过 终端 命令行安装"></a>通过 终端 命令行安装</h6><p>打开终端,在终端输入此命令<br><code>cp -R /Applications/Utilities/Terminal.app/Contents/Resources/Fonts/*.otf ~/Library/Fonts/</code><br>回车即可</p>]]></content>
<tags>
<tag> macOS </tag>
<tag> mac </tag>
<tag> 字体 </tag>
</tags>
</entry>
<entry>
<title>go go go 2019</title>
<link href="/2019/08/28/6aaf43c133c4.html"/>
<url>/2019/08/28/6aaf43c133c4.html</url>
<content type="html"><![CDATA[<pre><code>有点生疏了</code></pre>]]></content>
</entry>
<entry>
<title>判断字符是否是纯数字</title>
<link href="/2016/11/24/e13e51eae9f1.html"/>
<url>/2016/11/24/e13e51eae9f1.html</url>
<content type="html"><![CDATA[<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></pre></td><td class="code"><pre><span class="line"><span class="comment">//使用NSScanner类, </span></span><br><span class="line">[<span class="keyword">self</span> isPureInt:text] <span class="comment">//传入字符串并调用方法判断</span></span><br><span class="line"></span><br><span class="line">- (<span class="type">BOOL</span>)isPureInt:(<span class="built_in">NSString</span>*)string{</span><br><span class="line"> <span class="built_in">NSScanner</span>* scan = [<span class="built_in">NSScanner</span> scannerWithString:string]; <span class="comment">//定义一个NSScanner,扫描string</span></span><br><span class="line"> <span class="type">int</span> val;</span><br><span class="line"> <span class="keyword">return</span> [scan scanInt:&val] && [scan isAtEnd];</span><br><span class="line">}</span><br></pre></td></tr></table></figure><span id="more"></span><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 同理 可以检测float double 等等格式</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//[scan scanInt:&val] </span></span><br><span class="line"><span class="comment">//扫描的Int类型放入val</span></span><br><span class="line"><span class="comment">//根据NSScanner的机制,如果扫描到结果需要的数据,那么它就会停在数据结尾的下一个字符处</span></span><br><span class="line"><span class="comment">//例如:string = @"12ccf12";如果扫描Int类型,那么第一次扫描到第二个字符处就停止了,如果要扫描全部需要进行循环判断</span></span><br><span class="line"><span class="comment">//扫描结束后,没有到string的结尾,那么[scan isAtEnd]为NO</span></span><br><span class="line"><span class="comment">//所以</span></span><br><span class="line"><span class="comment">//[scan isAtEnd] </span></span><br><span class="line"> <span class="comment">//判断是否到结尾</span></span><br><span class="line"><span class="comment">//这样就能保证一遍扫描到结尾的数据全部是int,[scan scanInt:&val] 和[scan isAtEnd]都为YES;</span></span><br><span class="line"><span class="comment">//结果isPureInt 返回YES;</span></span><br><span class="line"><span class="comment">//类似其他的判断也可以参考NSScanner</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<tags>
<tag> iOS </tag>
</tags>
</entry>
<entry>
<title>15分钟快速学会git</title>
<link href="/2016/09/24/c859e4c3dee5.html"/>
<url>/2016/09/24/c859e4c3dee5.html</url>
<content type="html"><![CDATA[<ol start="0"><li><p>初始化仓库<br> <strong>git init</strong> : 初始化仓库</p></li><li><p>检查状态<br> <strong>git status</strong> : 查看git状态</p></li><li><p>添加文件到缓存区<br> <strong>git add .</strong> : 把文件添加到缓存区</p></li><li><p>Committing<br> <strong>git commit -m “Add file”</strong> : 提交到缓存区</p><span id="more"></span></li><li><p>History<br> <strong>git log</strong> : 查看历史</p></li><li><p>远程存储库<br> <strong>git remote add origin <git库地址></strong> : 添加到远端git库</p></li><li><p>Pushing Remotely<br> <strong>git push -u origin master</strong> : 把master分支推到远端服务器</p></li><li><p>Pulling Remotely<br><strong>git pull origin master</strong> : 从远端服务器master分支拉取</p></li><li><p>Differences 比较提交<br><strong>git diff HEAD</strong> : 比较工作目录与上次提交时之间的所有差别</p></li><li><p>Staged Differences<br><strong>git diff –staged</strong> </p></li><li><p>Resetting the Stage<br><strong>git reset <file octofamily/octodog.txt></strong></p></li><li><p>Undo 撤销<br><strong>git checkout – <file></strong> : 撤销文件自从上次提交的所有更改</p></li><li><p>Branching Out 分支<br><strong>git branch clean_up</strong> : 创建名为clean_up的分支</p></li><li><p>Switching Branch 切换分支<br><strong>git checkout clean_up</strong> : 切换到clean_up分支</p></li><li><p>Removing All The Things 删除所有文件<br><strong>git rm ‘<file name>‘</strong> : 删除文件 (有个单引号)</p></li><li><p>Committing Branch Changes 提交分支中的变换<br><strong>git commit -m “Remove all the cats”</strong> : commit</p></li><li><p>Switching Branch 切回 主分支<br><strong>git checkout master</strong> : 回到master主分支</p></li><li><p>Preparing to Merge<br><strong>git merge clean_up</strong> : 当前在master主分支下操作, 把clean_up分支合并到master主分支</p></li><li><p>Delete Branch 为了保持工作区干净 删除用完的分支</p><p><strong>git branch -d clean_up</strong> 删除本地分支 <strong>-D</strong> 是强制删除<br>删除远端 多个push<br><strong>git push origin :serverfix</strong> : <strong>冒号写法</strong> 冒号前面空格不能少, 原理是把一个空分支push到server上,相当于删除该分支<br><strong>git push origin –delete serverfix</strong> –delete写法</p></li><li><p>The Final Push 最后一步 push<br><strong>git push</strong> : 推送到远端服务器</p></li></ol>]]></content>
<tags>
<tag> git </tag>
</tags>
</entry>
<entry>
<title>隐藏navigationBar底部的黑线shadowImage</title>
<link href="/2016/09/23/9adbb56f98f1.html"/>
<url>/2016/09/23/9adbb56f98f1.html</url>
<content type="html"><![CDATA[<ol><li><p>直接设置navigationBar的shadowImage和backgroundImage, 需先让translucent属性设置为NO</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></pre></td><td class="code"><pre><span class="line">-(<span class="type">void</span>)removeBlackLine {</span><br><span class="line"> [<span class="keyword">self</span>.navigationController.navigationBar setBackgroundImage:[<span class="built_in">UIImage</span> new] forBarPosition:<span class="built_in">UIBarPositionAny</span> barMetrics:<span class="built_in">UIBarMetricsDefault</span>]; </span><br><span class="line"> [<span class="keyword">self</span>.navigationController.navigationBar setShadowImage:[<span class="built_in">UIImage</span> new]]; </span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>循环遍历navigationBar的子视图,找到高度小于1的黑线, 在appear是隐藏, disappear时再显示(推荐)<span id="more"></span></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><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">@implementation</span> <span class="title">ViewController</span> </span>{</span><br><span class="line"> <span class="built_in">UIImageView</span> *navBarHairlineImageView;</span><br><span class="line">}</span><br><span class="line">- (<span class="type">void</span>)viewWillAppear:(<span class="type">BOOL</span>)animated {</span><br><span class="line">[<span class="variable language_">super</span> viewWillAppear:animated];</span><br><span class="line"> navBarHairlineImageView.hidden = <span class="literal">YES</span>;</span><br><span class="line">}</span><br><span class="line">- (<span class="type">void</span>)viewWillDisappear:(<span class="type">BOOL</span>)animated {</span><br><span class="line">[<span class="variable language_">super</span> viewWillDisappear:animated];</span><br><span class="line"> navBarHairlineImageView.hidden = <span class="literal">NO</span>;</span><br><span class="line">} </span><br><span class="line">- (<span class="type">void</span>)viewDidLoad {</span><br><span class="line"> [<span class="variable language_">super</span> viewDidLoad];</span><br><span class="line"> navBarHairlineImageView= [<span class="keyword">self</span> findHairlineImageViewUnder:<span class="keyword">self</span>.navigationController.navigationBar];</span><br><span class="line"> <span class="comment">// Do any additional setup after loading the view, typically from a nib.</span></span><br><span class="line">}</span><br><span class="line">- (<span class="built_in">UIImageView</span> *)findHairlineImageViewUnder:(<span class="built_in">UIView</span> *)view { </span><br><span class="line"> <span class="keyword">if</span> ([view isKindOfClass:<span class="built_in">UIImageView</span>.class] && view.bounds.size.height <= <span class="number">1.0</span>) { </span><br><span class="line"> <span class="keyword">return</span> (<span class="built_in">UIImageView</span> *)view; </span><br><span class="line"> } </span><br><span class="line"> <span class="keyword">for</span> (<span class="built_in">UIView</span> *subview <span class="keyword">in</span> view.subviews) { </span><br><span class="line"> <span class="built_in">UIImageView</span> *imageView = [<span class="keyword">self</span> findHairlineImageViewUnder:subview]; </span><br><span class="line"> <span class="keyword">if</span> (imageView) { </span><br><span class="line"> <span class="keyword">return</span> imageView; </span><br><span class="line"> } </span><br><span class="line"> } </span><br><span class="line"> <span class="keyword">return</span> <span class="literal">nil</span>; </span><br><span class="line">} </span><br></pre></td></tr></table></figure></li><li><p>切去超出部分, 此方法会把状态栏给切掉</p><figure class="highlight objectivec"><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="type">void</span>)useClipsToBoundsRemoveBlackLine { <span class="keyword">self</span>.navigationController.navigationBar.clipsToBounds = <span class="literal">YES</span>; </span><br><span class="line">} </span><br></pre></td></tr></table></figure></li></ol>]]></content>
<tags>
<tag> iOS </tag>
</tags>
</entry>
<entry>
<title>更改rootViewController时添加动画</title>
<link href="/2016/09/20/01edb6427252.html"/>
<url>/2016/09/20/01edb6427252.html</url>
<content type="html"><![CDATA[<p>当需要更换Window的rootViewController时,怎么给这个过程添加动画呢?</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></pre></td><td class="code"><pre><span class="line">[<span class="built_in">UIView</span> transitionWithView:[[<span class="built_in">UIApplication</span> sharedApplication].delegate window]</span><br><span class="line"> duration:<span class="number">0.3</span></span><br><span class="line"> options:<span class="built_in">UIViewAnimationOptionTransitionCrossDissolve</span></span><br><span class="line"> animations:^{</span><br><span class="line"> [[[<span class="built_in">UIApplication</span> sharedApplication].delegate window] setRootViewController:viewController];</span><br><span class="line"> }</span><br><span class="line"> completion:<span class="literal">NULL</span>];</span><br></pre></td></tr></table></figure><p>这样写咋看咋对, 试试也是对的, <span id="more"></span> 但当横屏时会发现动画很奇怪, 后来在stackoverflow看到一个解决办法</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></pre></td><td class="code"><pre><span class="line">[<span class="built_in">UIView</span> transitionWithView:[[<span class="built_in">UIApplication</span> sharedApplication].delegate window]</span><br><span class="line"> duration:<span class="number">0.3</span></span><br><span class="line"> options:<span class="built_in">UIViewAnimationOptionTransitionCrossDissolve</span></span><br><span class="line"> animations:^{</span><br><span class="line"> <span class="type">BOOL</span> oldState = [<span class="built_in">UIView</span> areAnimationsEnabled];</span><br><span class="line"> [<span class="built_in">UIView</span> setAnimationsEnabled:<span class="literal">NO</span>];</span><br><span class="line"> [[[<span class="built_in">UIApplication</span> sharedApplication].delegate window] setRootViewController:viewController];</span><br><span class="line"> [<span class="built_in">UIView</span> setAnimationsEnabled:oldState];</span><br><span class="line"> }</span><br><span class="line"> completion:<span class="literal">NULL</span>];</span><br></pre></td></tr></table></figure>]]></content>
<tags>
<tag> iOS </tag>
</tags>
</entry>
<entry>
<title>AlertController的Click方法封装</title>
<link href="/2016/08/31/6f517186ba1f.html"/>
<url>/2016/08/31/6f517186ba1f.html</url>
<content type="html"><![CDATA[<p>封装的AlertController, 不至于每次写alert时 好多Block回调;<br>先上 <a href="https://github.com/ijunfly/JFAlertViewController">JFAlertViewController</a>地址 <a href="https://github.com/ijunfly/JFAlertViewController">https://github.com/ijunfly/JFAlertViewController</a></p><p>每次写AlertView时每个按钮都要写一个Block来回调方法, 这样会使代码太多</p><p>创建一个继承于JFAlertViewController的属性对象</p><figure class="highlight objectivec"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">@property</span> (<span class="keyword">strong</span>, <span class="keyword">nonatomic</span>) JFAlertViewController *alertAllVC;</span><br></pre></td></tr></table></figure><p>初始化时要遵循delegate和dataSource</p><span id="more"></span><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">pragma</span> mark - getting</span></span><br><span class="line">- (JFAlertViewController *)alertAllVC {</span><br><span class="line"> <span class="keyword">if</span> (!_alertAllVC) {</span><br><span class="line"> _alertAllVC = [JFAlertViewController alertControllerWithTitle:<span class="string">@"我是标题"</span> message:<span class="string">@"我是消息, 消息内容的消息..."</span> preferredStyle:<span class="built_in">UIAlertControllerStyleAlert</span>];</span><br><span class="line"> _alertAllVC.delegate = <span class="keyword">self</span>;</span><br><span class="line"> _alertAllVC.dataSource = <span class="keyword">self</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> _alertAllVC;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>然后就可以写dataSource和delegate方法了</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></pre></td><td class="code"><pre><span class="line"><span class="comment">//返回选项的个数 (cancel按钮不计算在内)</span></span><br><span class="line">- (<span class="built_in">NSUInteger</span>)numberOfIndexsInJFAlertView:(JFAlertViewController *)alertView;</span><br><span class="line"><span class="comment">//返回选项的title</span></span><br><span class="line">- (<span class="built_in">NSString</span> *)JFAlertView:(JFAlertViewController *)alertView titleAtIndexNumber:(<span class="built_in">NSUInteger</span>)index;</span><br><span class="line"><span class="keyword">@optional</span></span><br><span class="line"><span class="comment">//返回cancel按钮title, 默认是:"取消"</span></span><br><span class="line">- (<span class="built_in">NSString</span> *)cancelButtonTitleInJFAlertView:(JFAlertViewController *)alertView;</span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 选项的点击事件</span></span><br><span class="line">- (<span class="type">void</span>)JFAlertView:(JFAlertViewController *)alertView clickedAtIndex:(<span class="built_in">NSUInteger</span>)index;</span><br><span class="line"></span><br><span class="line"><span class="comment">//cancel按钮的点击事件</span></span><br><span class="line">- (<span class="type">void</span>)JFAlertViewCancel:(JFAlertViewController *)alertView;</span><br></pre></td></tr></table></figure><p>欢迎指正…</p><p>demo改天再传….</p>]]></content>
<tags>
<tag> iOS </tag>
</tags>
</entry>
<entry>
<title>放羊人与砍柴人的故事</title>
<link href="/2016/08/30/3023662f8e20.html"/>
<url>/2016/08/30/3023662f8e20.html</url>
<content type="html"><![CDATA[<p>你是砍柴的,他是放羊的,你和他聊了一天,他的羊吃饱了,你的柴呢? 砍柴的陪不起放羊的——请放弃你的无效社交!</p><p>你是砍柴的,他是放羊的,你和他聊了一天,如是你学会了放羊技巧,<span id="more"></span>原来羊是这么放的,他学会了砍柴技能,原来柴要这样砍——三人行必有我师,永远保持空杯的状态!</p><p>你是砍柴的,他是放羊的,你和他聊了一天,他决定把他的羊跟你的柴交换,于是你有了羊,他也有了柴——等价交换,不要看不起任何人,天生我才必有用!</p><p>你是砍柴的,他是放羊的,你和他聊了一天,他把他买羊的客户介绍给了你,你把你买柴的客户介绍给了他,于是你们各自的生意越做越大——资源整合很重要!</p><p>你是砍柴的,他是放羊的,你和他聊了一天,你们决定合作一起开个烤全羊的店,你的柴烤出来的羊很美味,他的羊纯天然的,几年后你们公司上市了——没有完美的个人,只有完美的团队!<br>……</p><p>其实面对同一件事物 心态不一样 结果就会不一样!我想说,聊可以瞎聊,沟通却是有目的的。</p><img src="/2016/08/30/3023662f8e20/160830-fangyangren.jpg" class="">]]></content>
<tags>
<tag> 故事 </tag>
</tags>
</entry>
<entry>
<title>Xcode插件管理工具-Alcatraz</title>
<link href="/2016/08/26/7472c647ead7.html"/>
<url>/2016/08/26/7472c647ead7.html</url>
<content type="html"><![CDATA[<h1 id="Xcode插件"><a href="#Xcode插件" class="headerlink" title="Xcode插件"></a>Xcode插件</h1><p><strong>Alcatraz</strong>是管理Xcode插件的插件, 集成在Xcode图形界面中.<br><em>Xcode8中Apple禁止了Xcode安装插件</em></p><p>手动安装Alcatraz, 在GitHub主页上找搜索<a href="https://github.com/alcatraz/Alcatraz">Alcatrazde</a> , 或者浏览器地址栏直接输入<a href="https://github.com/alcatraz/Alcatraz">https://github.com/alcatraz/Alcatraz</a></p><img src="/2016/08/26/7472c647ead7/0826-1472176469450.png" class=""><ul><li><span id="more"></span>点击[Clone or download]选择 Download ZIP (如上图),进行下载。</li></ul><p>下载完,解压ZIP, 双击打开 .xcodeproj 可执行文件,会打开Xcode,之后运行这个项目工程</p><img src="/2016/08/26/7472c647ead7/0826-1472176649167.png" class=""><p>运行完,会出现一个会话弹出框,不要慌,这不是出现什么错误了(其实我刚开始看见这个的时候慌了一下),淡定的点击 Load Bundles</p><img src="/2016/08/26/7472c647ead7/0826-1472176707103.png" class=""><p>然后关闭Xcode(或者command + Q), 重新打开Xcode<br>点击Windows可以看到Package Manager(Shift+Command+9)</p><img src="/2016/08/26/7472c647ead7/0826-1472176837716.png" class=""><p>此时就可以打开Alcatraz管理工具了</p><img src="/2016/08/26/7472c647ead7/0826-1472177132229.png" class=""><p><a href="http://www.cocoachina.com/ios/20160122/15080.html">Xcode 插件优缺点对比(推荐 20 款插件)</a></p><p><a href="http://www.tuicool.com/articles/zUZnAfj">工作中的常用插件 for Xcode</a></p>]]></content>
<tags>
<tag> Xcode </tag>
<tag> iOS </tag>
</tags>
</entry>
<entry>
<title>git基础命令</title>
<link href="/2016/08/25/64b2c31ab32a.html"/>
<url>/2016/08/25/64b2c31ab32a.html</url>
<content type="html"><![CDATA[<p><strong>pwd</strong> 命令用于显示当前目录</p><p><strong>git init</strong>命令把这个目录变成Git可以管理的仓库</p><p>现有的仓库 <strong>git remote add origin <a href="mailto:git@192.168.1.235">git@192.168.1.235</a>:iOSTeam/xxx.git</strong> 这个要替换项目地址</p><p><strong>ssh-add</strong> ~/.ssh/xxx_id_rsa 添加sshKey 不至于每次输入密码</p><p>用ls -ah命令就可以看见所有文件</p><p><strong>git add</strong> 文件名字.后缀 git add . // 所有文件</p><p><strong>git status</strong> 状态<br> <span id="more"></span><br><strong>git commit -m “xxx”</strong> 提交</p><p><strong>git log</strong> 命令查看<br>git log –pretty=oneline 参数 显示 commit id(版本号)</p><p><strong>git diff</strong> 查看修改内容</p><p><strong>git reset</strong> 命令 回退到上一个版本 git reset –hard HEAD^^^^ / HEAD~4<br>还有个方法只要上面的命令行窗口还没有被关掉,你就可以顺着往上找啊找啊,找到那个append GPL的commit id是3628164…,于是就可以指定回到未来的某个版本:<br>git reset –hard 3628164</p><p><strong>git reflog</strong> 用来记录你的每一次命令</p><p><strong>cat readme.txt</strong> 打开文件</p><p><strong>git checkout -</strong> <file> 可以丢弃工作区的修改 , 没有–,就变成了“切换到另一个分支”的命令,<br>git reset HEAD <file> 可以把暂存区的修改撤销掉(unstage),重新放回工作区:</p><p><strong>git rm</strong> 删掉,</p><hr><p><strong>git push origin master</strong> 推到远程master分支</p>]]></content>
<tags>
<tag> git </tag>
</tags>
</entry>
<entry>
<title>Hello World</title>
<link href="/2016/08/20/31047e7c1977.html"/>
<url>/2016/08/20/31047e7c1977.html</url>
<content type="html"><![CDATA[<p>Welcome to <a href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/">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">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><ul><li><span id="more"></span><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></li></ul><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">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">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">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">Deployment</a></p>]]></content>
</entry>
<entry>
<title>新的开篇</title>
<link href="/2016/08/15/02fee1cc85dd.html"/>
<url>/2016/08/15/02fee1cc85dd.html</url>
<content type="html"><![CDATA[<h1 id="暂时的离别是为了再次相聚时的感动"><a href="#暂时的离别是为了再次相聚时的感动" class="headerlink" title="暂时的离别是为了再次相聚时的感动"></a>暂时的离别是为了再次相聚时的感动</h1><hr><h4 id="离别"><a href="#离别" class="headerlink" title="离别"></a>离别</h4><p>离别的时候<br>每一句话都是那么重<br>缓缓地扣击着我们的心灵<br>窗被敲开了<br>我们诉说着回忆中的快乐<br>回想著一张张可爱的笑脸<br>院子里,操场上<br>充满了甜甜的空气 </p><ul><li><span id="more"></span>离别的时候<br>每一句话都是那么轻<br>轻轻地说着离别时的感言<br>轻轻的拉着彼此的手<br>轻轻地在耳际说声对不起<br>或永远祝福你</li></ul><p>离别的时候<br>每一句话都显得那么悲伤<br>离别时的感动在顷刻间爆发<br>我们,我们,我们<br>独自沉浸在自己的感伤中<br>渐渐的平息…… </p><p>离别的时候<br>每一句话都显得那么珍贵<br>仔细的听著那熟悉的声音<br>把每种都印刻在记忆里 </p><p>望著他们远去的背影,我知道,我们离别了<br>我们带著共同的回忆和永远的祝福<br>各自奔向远方……<br>轻轻哼一首离别的歌~<br>眼里噙满了泪…… </p><h4 id="重逢"><a href="#重逢" class="headerlink" title="重逢"></a>重逢</h4><p>重逢的时候<br>那是心情的又一次触动<br>惊喜的表情<br>熟悉的面庞<br>回忆中的甜蜜<br>一瞬间在脑海中隐现<br>于是,永远成为了所谓的缘分的代表<br>重逢…惊喜…<br>重逢的时候<br>那是思念的又一次宣泄<br>深情的一个拥抱<br>紧紧的一个握手<br>彼此的心轻鬆了许多<br>才发现思念是一种病<br>重逢…思念……<br>重逢的时候<br>那是记忆的又一次翻新<br>彼此回忆著孩提时的美好<br>诉说着自己的苦恼<br>谈论着朋友的生活<br>讲述着自己无奈的过往<br>重逢…记忆…<br>重逢的时候<br>那是时间的又一次停滞<br>那一刻,时间终于停了<br>自己终于可以放假<br>感动的身体一时瘫在那里<br>重逢时的感动告诉了时光老人<br>时间不能改变的东西……<br>重逢…感动…<br>重逢的时候,那是一阵欣喜,一阵感动<br>欣喜之余还有一丝的忧伤<br>因为我们毕竟还要赶路<br>那么多线终有相交的一点<br>可是相交以后注定还要分别<br>但是,至少我明白<br>暂时的离别是为了再次相聚时的感动…… </p>]]></content>
<tags>
<tag> 杂谈 </tag>
</tags>
</entry>
</search>