-
Notifications
You must be signed in to change notification settings - Fork 0
/
feed.xml
814 lines (569 loc) · 55.7 KB
/
feed.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
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>面向自由编程 - Articles</title>
<description>Freelf's Blog</description>
<link>
</link>
<item>
<title>macOS 14.4远程管理问题解决</title>
<description><p>最近把家里的 Mac Studio 格盘重新安装了一下系统,并且升级到了 14.4。因为使用 Mac Studio 做网关,并且希望可以远程访问 Mac Studio,所以在重装系统之前一直都开了远程管理。这次装完系统后,按照惯例开启远程管理。配完后发现远程不生效,又重新操作了几次,终于发现了问题,原来是远程管理添加了用户,关掉之后,用户就没有了。
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/uPic/mHzjWu.png" alt="" />
经过搜索之后,发现<a href="https://discussionschinese.apple.com/thread/255530806?sortBy=best">这个帖子</a>有同样的问题,但是没有解决方案,但是底下有人回答说是 GUI 的问题。我就想是不是用命令行可以开启。经过搜索,发现可以通过 kickstart 来实现。kickstart 文档在<a href="https://ss64.com/mac/kickstart.html">这里</a>。主要用到了以下这个命令:</p>
</description>
<pubDate>Wed, 17 Apr 2024 00:00:00 +0000</pubDate>
<link>
/macOS-14.4%E8%BF%9C%E7%A8%8B%E7%AE%A1%E7%90%86%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3</link>
<guid isPermaLink="true">/macOS-14.4%E8%BF%9C%E7%A8%8B%E7%AE%A1%E7%90%86%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3</guid>
</item>
<item>
<title>新疆游,一次不完美的旅途</title>
<description><h1 id="新疆游记">新疆游记</h1>
</description>
<pubDate>Wed, 22 Dec 2021 00:00:00 +0000</pubDate>
<link>
/%E6%96%B0%E7%96%86%E6%B8%B8-%E4%B8%80%E6%AC%A1%E4%B8%8D%E5%AE%8C%E7%BE%8E%E7%9A%84%E6%97%85%E9%80%94</link>
<guid isPermaLink="true">/%E6%96%B0%E7%96%86%E6%B8%B8-%E4%B8%80%E6%AC%A1%E4%B8%8D%E5%AE%8C%E7%BE%8E%E7%9A%84%E6%97%85%E9%80%94</guid>
</item>
<item>
<title>Aspects源码分析</title>
<description><p>最近有个需求用到了Aspects这个库,用的过程中发现了一些问题,为了解决问题,花了几天时间精读了一遍Aspects的源码。读的过程中发现这个库如果发散着去读,可以了解Objective-C这个语言的方方面面。这篇文章就不发散了,本篇集中记录Aspects如何去进行Hook方法的。后面可能会写一些Aspects发散的文章。本篇分析采用从入口方法开始,然后用到哪个方法会分析哪个方法。</p>
</description>
<pubDate>Wed, 09 Dec 2020 00:00:00 +0000</pubDate>
<link>
/Aspects%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90</link>
<guid isPermaLink="true">/Aspects%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90</guid>
</item>
<item>
<title>初识iOS中的动态库和静态库</title>
<description><p>由于最近研究组件化后调试时二进制映射源码的功能,发现需要对开发中的动态库和静态库需要有一些了解。所以就有了这篇文章,由于只是了解,并没有深入到编译层面,所以本篇文章只是简单了解一些库的知识,并不深入。</p>
<h2 id="静态库-vs-动态库">静态库 vs 动态库</h2>
<p>平常开发的时候会接触一些库的文件,比如<code class="highlighter-rouge">.a</code>、<code class="highlighter-rouge">.tbd</code>、<code class="highlighter-rouge">.framework</code>结尾的文件,甚至以前还有<code class="highlighter-rouge">.dylib</code>结尾的。由于以前一直没忙于工作,所以也没有细致的研究这些文件结尾的区别。只是傻傻的以为<code class="highlighter-rouge">.a</code>结尾的是静态库,<code class="highlighter-rouge">.framework</code>结尾的是动态库。现在看来以前是真的傻。现在来看一下静态库和动态库的区别。</p>
<h3 id="静态库">静态库</h3>
<p>如果我们的app依赖一个静态库,在链接阶段会把依赖静态库的部分合并到app的<strong>可执行文件中</strong>(app的<strong>可执行文件</strong>指的是app包内容里面同名的一个文件)。静态库的文件名后缀是<code class="highlighter-rouge">.a</code>或<code class="highlighter-rouge">.framework</code>。</p>
<h3 id="动态库">动态库</h3>
<p>编译app时并不会把动态库合并到app的<strong>可执行文件中</strong>,而是在程序启动的时候加载动态库到内存中。其中动态库分<strong>动态链接库</strong>和<strong>动态加载库</strong>两种。</p>
<ul>
<li><strong>动态链接库</strong>:在编译阶段需要指定app需要依赖哪些动态库。当运行可执行文件时,如果系统还没有加载过这些库时,就会随着运行可执行文件的加载一起加载这些动态库。如果有多个可执行文件依赖同一个动态库,不会重复加载。</li>
<li><strong>动态加载库</strong>:编译阶段不需要指定app需要依赖哪些动态库。当运行过程中需要加载某个动态库时,就会用<code class="highlighter-rouge">dlopen</code>函数动态的把库加载到内存中使用。</li>
</ul>
</description>
<pubDate>Sun, 19 Jul 2020 00:00:00 +0000</pubDate>
<link>
/%E5%88%9D%E8%AF%86iOS%E4%B8%AD%E7%9A%84%E5%8A%A8%E6%80%81%E5%BA%93%E5%92%8C%E9%9D%99%E6%80%81%E5%BA%93</link>
<guid isPermaLink="true">/%E5%88%9D%E8%AF%86iOS%E4%B8%AD%E7%9A%84%E5%8A%A8%E6%80%81%E5%BA%93%E5%92%8C%E9%9D%99%E6%80%81%E5%BA%93</guid>
</item>
<item>
<title>Ghost S1复刻 & Hackintosh</title>
<description><p>由于年初疫情的原因,去年装的黑苹果终于可以用来干点正事了(关于去年的黑苹果配置可以看前一篇文章),在家办公一直使用黑苹果来开发。疫情渐渐远去,慢慢开始复工,复工后又开始用19年13寸中配的MBP办公。没有对比就没有伤害,没用黑苹果之前也没感觉这台笔记本会这么慢,编译一次项目2分钟的时长实在忍不了。经过权衡决定组装一台黑苹果在公司用。</p>
</description>
<pubDate>Wed, 03 Jun 2020 00:00:00 +0000</pubDate>
<link>
/Ghost-S1%E5%A4%8D%E5%88%BB-&-Hackintosh</link>
<guid isPermaLink="true">/Ghost-S1%E5%A4%8D%E5%88%BB-&-Hackintosh</guid>
</item>
<item>
<title>WKWebView离线包开发小记</title>
<description><p>随着项目里面Web页面内容越来越多,H5的加载速度变得越来越重要。在H5同学提出需求前就看过有关优化的文章。当时没有细致的去看,本来以为做起来轻车熟路,但是真做起来坑还是不少。下面记录一下整个优化过程。</p>
<h2 id="优化思路">优化思路</h2>
<p>一个WebView加载的过程大约有以下几个步骤(内容来自于<a href="https://mp.weixin.qq.com/s/0OR4HJQSDq7nEFUAaX1x5A">腾讯Bugly的文章</a>):</p>
<blockquote>
<p>初始化 WebView -&gt; 请求页面 -&gt; 下载数据 -&gt; 解析HTML -&gt; 请求 js/css 资源 -&gt; dom 渲染 -&gt; 解析 JS 执行 -&gt; JS 请求数据 -&gt; 解析渲染 -&gt; 下载渲染图片</p>
</blockquote>
</description>
<pubDate>Mon, 18 May 2020 00:00:00 +0000</pubDate>
<link>
/WKWebView%E7%A6%BB%E7%BA%BF%E5%8C%85%E5%BC%80%E5%8F%91%E5%B0%8F%E8%AE%B0</link>
<guid isPermaLink="true">/WKWebView%E7%A6%BB%E7%BA%BF%E5%8C%85%E5%BC%80%E5%8F%91%E5%B0%8F%E8%AE%B0</guid>
</item>
<item>
<title>近期黑苹果折腾小记</title>
<description><p>一直以来都想装一台黑苹果折腾一下,去年10月终于组装了一台。在近期也把电脑折腾完美了。配置如下:</p>
</description>
<pubDate>Fri, 24 Apr 2020 00:00:00 +0000</pubDate>
<link>
/%E8%BF%91%E6%9C%9F%E9%BB%91%E8%8B%B9%E6%9E%9C%E6%8A%98%E8%85%BE%E5%B0%8F%E8%AE%B0</link>
<guid isPermaLink="true">/%E8%BF%91%E6%9C%9F%E9%BB%91%E8%8B%B9%E6%9E%9C%E6%8A%98%E8%85%BE%E5%B0%8F%E8%AE%B0</guid>
</item>
<item>
<title>解决Xcode插件突然失效问题</title>
<description><p>今天工作,突然发现自己的Xcode插件不能用了,原本以为进偏好设置-&gt;扩展-&gt;Xcode Source Editor里面把插件钩上就行呢。但是到了里面突然发现扩展里面的Xcode Source Editor选项都不见了。重新打开插件也不行,重启也不行,反正就是扩展里面没有Xcode Source Editor这个选项。通过Google搜索了一番,找到了一个简单的解决办法:</p>
<ol>
<li>退出Xcode</li>
<li>在应用程序里面给Xcode重命名,名字随便起</li>
<li>打开重命名的Xcode</li>
<li>退出Xcode</li>
<li>把Xcode重新命名为Xcode
通过上面一系列操作,扩展里面终于可以看到Xcode Source Editor了。折腾了半个小时!终于又可以愉快的码代码了~</li>
</ol>
</description>
<pubDate>Wed, 20 Nov 2019 00:00:00 +0000</pubDate>
<link>
/%E8%A7%A3%E5%86%B3Xcode%E6%8F%92%E4%BB%B6%E7%AA%81%E7%84%B6%E5%A4%B1%E6%95%88%E9%97%AE%E9%A2%98</link>
<guid isPermaLink="true">/%E8%A7%A3%E5%86%B3Xcode%E6%8F%92%E4%BB%B6%E7%AA%81%E7%84%B6%E5%A4%B1%E6%95%88%E9%97%AE%E9%A2%98</guid>
</item>
<item>
<title>Meta(一):Hello Metal,第一个Metal应用</title>
<description><p>因为和几个志同道合的同学开了个小专栏,本文发在小专栏上,这里仅做记录。有兴趣的同学,欢迎订阅小专栏,小专栏还有其他好看的文章。<a href="https://xiaozhuanlan.com/topic/7324865901">地址</a>。</p>
</description>
<pubDate>Mon, 30 Sep 2019 00:00:00 +0000</pubDate>
<link>
/Meta(%E4%B8%80)-Hello-Metal,%E7%AC%AC%E4%B8%80%E4%B8%AAMetal%E5%BA%94%E7%94%A8</link>
<guid isPermaLink="true">/Meta(%E4%B8%80)-Hello-Metal,%E7%AC%AC%E4%B8%80%E4%B8%AAMetal%E5%BA%94%E7%94%A8</guid>
</item>
<item>
<title>iOS 13 ScrollView截图问题记录</title>
<description><p>最近有个需求,需要给TabelView截图。当时做的比较着急,从stackoverflow上面抄了如下一段代码,并且可以正常运行。代码如下:
```objc
UIImage* image = nil;
UIGraphicsBeginImageContext(_scrollView.contentSize);
{
CGPoint savedContentOffset = _scrollView.contentOffset;
CGRect savedFrame = _scrollView.frame;</p>
</description>
<pubDate>Tue, 24 Sep 2019 00:00:00 +0000</pubDate>
<link>
/iOS-13-ScrollView%E6%88%AA%E5%9B%BE%E9%97%AE%E9%A2%98%E8%AE%B0%E5%BD%95</link>
<guid isPermaLink="true">/iOS-13-ScrollView%E6%88%AA%E5%9B%BE%E9%97%AE%E9%A2%98%E8%AE%B0%E5%BD%95</guid>
</item>
<item>
<title>原型模式</title>
<description><p>前面讨论了工厂模式,这里接着探索创建型模式。在这里考虑一个订单系统,里面有一个保存订单的功能。要求是如果订单预定的产品数量超过1000,就需要把订单拆分成两份订单来保存。如果拆成两份后还是超过1000,那就继续拆分。知道每份订单数量不超过1000。至于为什么要拆分,是为了方便后续处理,后续是有人工来处理,每个人处理能力是1000。根据业务,目前订单类型有两种,企业订单和个人订单。</p>
</description>
<pubDate>Tue, 13 Aug 2019 00:00:00 +0000</pubDate>
<link>
/%E5%8E%9F%E5%9E%8B%E6%A8%A1%E5%BC%8F</link>
<guid isPermaLink="true">/%E5%8E%9F%E5%9E%8B%E6%A8%A1%E5%BC%8F</guid>
</item>
<item>
<title>Builder模式</title>
<description><p>前面讨论了工厂模式,这里接着探索创建类型的设计模式。在讨论工厂模式的时候提出了一个导出数据的应用框架。这里接着对这个框架做一些补充,这些补充的地方会用到Builder模式。</p>
<h2 id="场景问题">场景问题</h2>
<p>对于导出数据的框架,在导出的文件上会有一些约定的方式,比如导出成文本格式、数据库模式、xml格式等等。在工厂模式中,使用工厂模式解决了如何选择具体的导出方式,并没有涉及每种导出方式的实现。也就是说,在工厂模式里面,并没有讨论如何实现导出文本、数据库、PDF等具体的格式,这里就来讨论这个问题。
对于导出数据的应用框架,通常对于导出数据的导出内容和格式是有要求的,比如现在有如下要求:</p>
<ol>
<li>导出的文件,不管什么格式,必须有文件头、文件体和文件尾,文件头、文件体和文件尾之间要换行。</li>
<li>文件头需要以下描述信息:导出数据的日期和编号。</li>
<li>文件体表示文件的内容。</li>
<li>文件尾需要有导出人的信息。</li>
</ol>
</description>
<pubDate>Mon, 05 Aug 2019 00:00:00 +0000</pubDate>
<link>
/Builder%E6%A8%A1%E5%BC%8F</link>
<guid isPermaLink="true">/Builder%E6%A8%A1%E5%BC%8F</guid>
</item>
<item>
<title>Metal基础概念——利用GPU高效计算</title>
<description><p>Metal是Apple提供的一个可以让我们开发者直接和GPU对话的API。Metal在图像处理,并行计算方面通过发挥GPU的特性,极大提升了性能。</p>
</description>
<pubDate>Fri, 02 Aug 2019 00:00:00 +0000</pubDate>
<link>
/Metal%E5%9F%BA%E7%A1%80%E6%A6%82%E5%BF%B5-%E5%88%A9%E7%94%A8GPU%E9%AB%98%E6%95%88%E8%AE%A1%E7%AE%97</link>
<guid isPermaLink="true">/Metal%E5%9F%BA%E7%A1%80%E6%A6%82%E5%BF%B5-%E5%88%A9%E7%94%A8GPU%E9%AB%98%E6%95%88%E8%AE%A1%E7%AE%97</guid>
</item>
<item>
<title>工厂模式</title>
<description><p>最近重新学习设计模式,以前一直看的是Raywenderlich的书籍,总感觉不够深入。最近重新找了一本书来学习,所以以前的系列就不再继续写了,重新开始记录。这是第一篇,来学习一下工厂模式。
设计模式名字中带工厂的有三个。简单工厂,工厂方法,抽象工厂。本文就看一下这三种工厂的区别,以及从简单工厂到抽象工厂的演进。</p>
<h2 id="简单工厂">简单工厂</h2>
<p>严格来讲简单工厂并不是一个标准的设计模式,但是它太常用了,所以需要我们好好掌握它。</p>
</description>
<pubDate>Mon, 29 Jul 2019 11:16:52 +0000</pubDate>
<link>
/%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F</link>
<guid isPermaLink="true">/%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F</guid>
</item>
<item>
<title>白驹过隙--2018总结</title>
<description><p>2018 不知不觉就过去了,在 2018 年的尾巴公司决定实行 OKR,所以本文从工作、生活、学习、投资方面总结一下 2018,并制定一下 2019 的 OKR。</p>
</description>
<pubDate>Mon, 04 Feb 2019 23:45:52 +0000</pubDate>
<link>
/%E7%99%BD%E9%A9%B9%E8%BF%87%E9%9A%99-2018%E6%80%BB%E7%BB%93</link>
<guid isPermaLink="true">/%E7%99%BD%E9%A9%B9%E8%BF%87%E9%9A%99-2018%E6%80%BB%E7%BB%93</guid>
</item>
<item>
<title>读《Design-Patterns-by-Tutorials》笔记——Builder Pattern</title>
<description><p>构造器模式允许一步一步的创建一个复杂的对象而不是一次创建完成。这个模式包括三个主要类型,UML 图如下:
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/1538746972.png" alt="构造器模式" /></p>
</description>
<pubDate>Tue, 09 Oct 2018 15:45:52 +0000</pubDate>
<link>
/%E8%AF%BB-Design-Patterns-by-Tutorials-%E7%AC%94%E8%AE%B0-Builder-Pattern</link>
<guid isPermaLink="true">/%E8%AF%BB-Design-Patterns-by-Tutorials-%E7%AC%94%E8%AE%B0-Builder-Pattern</guid>
</item>
<item>
<title>读《Design-Patterns-by-Tutorials》笔记——Observer Pattern</title>
<description><p>观察者模式让一个对象观察另一个对象的改变。在本章节,你将学习两种实现观察者模式的方法:</p>
<ol>
<li>使用 KVO</li>
<li>使用一个<code class="highlighter-rouge">Observable</code>包装。</li>
</ol>
</description>
<pubDate>Thu, 04 Oct 2018 21:44:56 +0000</pubDate>
<link>
/%E8%AF%BB-Design-Patterns-by-Tutorials-%E7%AC%94%E8%AE%B0-Observer-Pattern</link>
<guid isPermaLink="true">/%E8%AF%BB-Design-Patterns-by-Tutorials-%E7%AC%94%E8%AE%B0-Observer-Pattern</guid>
</item>
<item>
<title>读《Design-Patterns-by-Tutorials》笔记——Memento Pattern</title>
<description><p>备忘录模式允许一个对象可以被保存和恢复。包括三个部分。</p>
<ol>
<li><strong>Originator</strong>: 需要被保存和恢复的对象。</li>
<li><strong>Memento</strong>: 代表保存的状态。</li>
<li><strong> Caretaker</strong>: 从 originator 请求保存,并且接收一个 memento 作为响应。caretaker 负责保管这些 memento,并在稍后向 originator 提供这些 memento来恢复 originator 的状态。
虽然不是严格要求,iOS通常使用<code class="highlighter-rouge">Encoder</code>来讲 originator 的状态保存到 memento,并且使用<code class="highlighter-rouge">Decoder</code>把 memento 恢复到 originator。这使编码和解码的逻辑可以通用。比如:<code class="highlighter-rouge">JSONEncoder</code>和<code class="highlighter-rouge">JSONDecoder</code>允许一个对象可以编码为 <code class="highlighter-rouge">JSON</code> 数据,也可以从<code class="highlighter-rouge">JSON</code>数据中解码。
UML 图如下:
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/1538272701.png" alt="" /></li>
</ol>
</description>
<pubDate>Wed, 03 Oct 2018 11:15:11 +0000</pubDate>
<link>
/%E8%AF%BB-Design-Patterns-by-Tutorials-%E7%AC%94%E8%AE%B0-Memento-Pattern</link>
<guid isPermaLink="true">/%E8%AF%BB-Design-Patterns-by-Tutorials-%E7%AC%94%E8%AE%B0-Memento-Pattern</guid>
</item>
<item>
<title>读《Design-Patterns-by-Tutorials》笔记——Singleton Pattern</title>
<description><p>单例模式限制一个类仅仅有一个实例。每个这个类的引用都指向同一个实例。在 iOS 开发中非常常见这种模式,因为 Apple 广泛使用单例模式。
UML 图如下:
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/1538101105.png" alt="" />
“singleton plus”模式也很常用,这个模式提供了一个共享单例,但是也允许其他实例被创建。</p>
</description>
<pubDate>Fri, 28 Sep 2018 12:27:27 +0000</pubDate>
<link>
/%E8%AF%BB-Design-Patterns-by-Tutorials-%E7%AC%94%E8%AE%B0-Singleton-Pattern</link>
<guid isPermaLink="true">/%E8%AF%BB-Design-Patterns-by-Tutorials-%E7%AC%94%E8%AE%B0-Singleton-Pattern</guid>
</item>
<item>
<title>读《Design Patterns by Tutorials》笔记——Strategy Pattern</title>
<description><p>策略模式定义了一系列可交换的对象,这些对象可以在运行时设置或者切换。这个模式有三部分。</p>
<ul>
<li><strong>使用策略的对象</strong>:在 iOS 开发中这个对象通常是一个<code class="highlighter-rouge">UIViewController</code>,但是理论上可以是任何需要交换表现的对象。</li>
<li><strong>策略协议</strong>:定义了每个策略必须实现的方法。</li>
<li><strong>策略对象</strong>:遵守策略协议的对象。</li>
</ul>
</description>
<pubDate>Thu, 27 Sep 2018 19:32:17 +0000</pubDate>
<link>
/%E8%AF%BB-Design-Patterns-by-Tutorials-%E7%AC%94%E8%AE%B0-Strategy-Pattern</link>
<guid isPermaLink="true">/%E8%AF%BB-Design-Patterns-by-Tutorials-%E7%AC%94%E8%AE%B0-Strategy-Pattern</guid>
</item>
<item>
<title>读《Design Patterns by Tutorials》笔记——Delegation Pattern</title>
<description><p>委托模式使一个对象能够使用另一个对象来提供数据或者执行一些任务,这个模式有三个部分,UML 图如下:
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/15344108237603.jpg" alt="" />
<!-- more --></p>
<ul>
<li>一个<strong>对象需要委托</strong>:也就是委托对象。通常这个对象有一个<code class="highlighter-rouge">weak</code> 属性 <code class="highlighter-rouge">delegate</code>,防止循环引用。</li>
<li>一个<strong>委托协议</strong>:这个协议定义了委托应该实现或者可能实现的方法。</li>
<li>一个<strong>委托</strong>:实现委托方法的对象。</li>
</ul>
</description>
<pubDate>Thu, 16 Aug 2018 16:44:01 +0000</pubDate>
<link>
/%E8%AF%BB-Design-Patterns-by-Tutorials-%E7%AC%94%E8%AE%B0-Delegation-Pattern</link>
<guid isPermaLink="true">/%E8%AF%BB-Design-Patterns-by-Tutorials-%E7%AC%94%E8%AE%B0-Delegation-Pattern</guid>
</item>
<item>
<title>读《Design Patterns by Tutorials》笔记——MVC</title>
<description><p>MVC 设计模式把对象分为三个不同的类型: Models,Views和 Controllers。
UML 图表示如下:
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/15341242390937.jpg" alt="" />
<!-- more -->
MVC 是在 iOS 编程中是非常常见的,因为 Apple 在 UIKit 中大量选用了这种设计模式。</p>
<ul>
<li><strong>Models</strong>保持应用数据,通常为 structs 或者简单的 classes。</li>
<li><strong>Views</strong>在屏幕上显示看的见的元素和 controls,通常为<code class="highlighter-rouge">UIView</code>的子类。</li>
<li><strong>Controllers</strong>在 models 和 views 中间协调,通常为<code class="highlighter-rouge">UIViewController</code>的子类。</li>
</ul>
</description>
<pubDate>Thu, 16 Aug 2018 16:15:13 +0000</pubDate>
<link>
/%E8%AF%BB-Design-Patterns-by-Tutorials-%E7%AC%94%E8%AE%B0-MVC</link>
<guid isPermaLink="true">/%E8%AF%BB-Design-Patterns-by-Tutorials-%E7%AC%94%E8%AE%B0-MVC</guid>
</item>
<item>
<title>读《Design Patterns by Tutorials》笔记——UML图</title>
<description><p>在学习设计模式之前,需要先来学习 UML 图。为什么先要学习 UML 图呢?因为后面的设计模式,我们都可以用一幅 UML 图来表示,所以当我们看到一幅 UML 图,就可以明白这是什么设计模式。然后如何用代码去实现它。
<!-- more --></p>
<h2 id="什么是-uml-图">什么是 UML 图</h2>
<p>UML 图包含类、协议、属性、方法和关系。
一个方块表示一个类。下面有一个非常简单的类 Dog:
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/1534068645.png" alt="Dog" />
为了表示一个类继承另外一个类,使用一个空心箭头:
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/1534068758.png" alt="继承" />
但是我们通常不把空心箭头叫做“inherits from”,而是叫成“is a”,例如:可以用下面的图表示 SheepDog 继承自 Dog 。
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/15340697063981.jpg" alt="" />
我们可以这样来理解这个图“SheepDog 是一个 Dog”。
在 UML 中使用一个简单的箭头表示属性,在 UML 中叫做“关联”。
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/15340698551173.jpg" alt="" />
通常把属性这个箭头叫做“has a”,比如下图:
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/15340699550757.jpg" alt="" />
也可以通过在箭头下面描述一个区间来表示一对多的关系,如下图表示一个 Farmer 有好多 Dog:
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/15340700470394.jpg" alt="" />
可以在一个 UML 图中使用多个箭头和方块,下面这个图表示一个 Farmer 有一个 SheepDog,这个 SheepDog 是一个 Dog。
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/15340702450982.jpg" alt="" />
在 UML 图中,也可以使用方块表示一个协议,为了区别类,需要在协议名前面加上«protocol»。
下图表示一个 PetOwning 协议:
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/15340703702062.jpg" alt="" />
使用一个空心箭头和虚线来表示一个类遵守了一个协议:
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/15340704239696.jpg" alt="" />
你可以把它理解成“实现”或者“符合”。
使用一个普通箭头和虚线来表示依赖。ULM 有意模糊依赖的概念。因此,无论什么时候使用依赖的关系都应该注释上使用的目的。比如,可以使用依赖箭头表示以下情况:</p>
<ul>
<li>一个 weak 属性或者 delegate;</li>
<li>一个作为参数传递给一个方法的对象,并且没有作为属性引用;</li>
<li>一种松耦合或者回调,比如:一个从 view 到 controller 的 IBAction</li>
</ul>
</description>
<pubDate>Fri, 10 Aug 2018 16:24:17 +0000</pubDate>
<link>
/%E8%AF%BB-Design-Patterns-by-Tutorials-%E7%AC%94%E8%AE%B0-UML%E5%9B%BE</link>
<guid isPermaLink="true">/%E8%AF%BB-Design-Patterns-by-Tutorials-%E7%AC%94%E8%AE%B0-UML%E5%9B%BE</guid>
</item>
<item>
<title>记录一次Reveal连接不上的问题</title>
<description><p>由于换了新电脑,项目也告一段落,Reveal有一段时间没用了。最近开了新的项目,需要频繁的UI调整,所以需要用到Reveal,结果死活无法在Reveal发现。我用的是断点的方法,比较简单,官方文档给了三种方法。详情请看<a href="http://support.revealapp.com/kb/getting-started/reveal-integration-guide">官方文档</a>。
<!--more-->
按照官方文档的断点教程走了一圈,运行App。Console打印出下面这句话:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Loading Reveal Server from /Applications/Reveal.app/Contents/SharedSupport/iOS-Libraries/RevealServer.framework/RevealServer...
Reveal Server was loaded successfully.
</code></pre></div></div>
<p>心里想着应该可以了,打开Reveal,瞬间打脸。跑官方demo也不行。后来结果搜索,发现有个<a href="http://support.revealapp.com/kb/tips-tricks/bonjour-debugging-why-cant-i-connect-to-my-app">调试方法</a>。跟着步骤来发现,在<code class="highlighter-rouge">curl -s -D - http://localhost:51441/application -o /dev/null</code>这一步,我失败了。
理清下思绪,应该是最后请求Reveal的服务器失败了,但是我试了一下,把localhost改为127.0.0.1就成功了。在终端ping localhost发现localhost没有绑定上。最后通过编辑/etc/hosts文件,把localhost绑定上,再次运行,终于搞定了!关于绑定localhost可以参照<a href="https://stackoverflow.com/questions/19732360/ping-cannot-resolve-localhost-unknown-host-os-x">这个回答</a>。</p>
</description>
<pubDate>Thu, 07 Jun 2018 22:00:29 +0000</pubDate>
<link>
/%E8%AE%B0%E5%BD%95%E4%B8%80%E6%AC%A1Reveal%E8%BF%9E%E6%8E%A5%E4%B8%8D%E4%B8%8A%E7%9A%84%E9%97%AE%E9%A2%98</link>
<guid isPermaLink="true">/%E8%AE%B0%E5%BD%95%E4%B8%80%E6%AC%A1Reveal%E8%BF%9E%E6%8E%A5%E4%B8%8D%E4%B8%8A%E7%9A%84%E9%97%AE%E9%A2%98</guid>
</item>
<item>
<title>记录一次解决安装fastlane报错过程</title>
<description><p>最近做新项目,因为将来会涉及到频繁打包去测试。为了提高打包效率,决定使用下 fastlane。按照流程先来安装。结果不出意料的报错了。</p>
</description>
<pubDate>Tue, 29 May 2018 22:50:06 +0000</pubDate>
<link>
/%E8%AE%B0%E5%BD%95%E4%B8%80%E6%AC%A1%E8%A7%A3%E5%86%B3%E5%AE%89%E8%A3%85fastlane%E6%8A%A5%E9%94%99%E8%BF%87%E7%A8%8B</link>
<guid isPermaLink="true">/%E8%AE%B0%E5%BD%95%E4%B8%80%E6%AC%A1%E8%A7%A3%E5%86%B3%E5%AE%89%E8%A3%85fastlane%E6%8A%A5%E9%94%99%E8%BF%87%E7%A8%8B</guid>
</item>
<item>
<title>Objective-C Runtime --- 消息发送</title>
<description><p>上篇文章分析了对象的数据结构,这篇我们就结合源码来分析下Objective-C最核心的东西——消息发送。在Objective-C中,我们调用方法,其实都是发送消息。发送消息为Objective-C增加了动态特性,下面我们就来看一下Objective-C的消息发送过程。
<!--more--></p>
<h1 id="objc_msgsend简介">objc_msgSend简介</h1>
<p>其实我们看大部分runtime文章,都是从这个函数看起的。在Objective-C中,我们调用方法的语法是这样的<code class="highlighter-rouge">[receiver message]</code>。编译期会把这个方法调用转换成下面这个函数:</p>
</description>
<pubDate>Sun, 20 May 2018 19:01:38 +0000</pubDate>
<link>
/Objective-C-Runtime-%E6%B6%88%E6%81%AF%E5%8F%91%E9%80%81</link>
<guid isPermaLink="true">/Objective-C-Runtime-%E6%B6%88%E6%81%AF%E5%8F%91%E9%80%81</guid>
</item>
<item>
<title>Objective-C Runtime —— 基础数据结构</title>
<description><p>iOS工作两年了,几乎每次面试都会被问到Runtime的东西,自己一直没有系统的学习过Runtime。正好这段时间比较闲,自己也想深入的学习下iOS。所以那就先了解下基础的东西吧。以前听到Runtime一直感觉很高深,什么黑魔法啊一堆名词,其实去了解下的话,没有那么神奇。这篇文章分三大部分来介绍Runtime,是一个循序渐进的过程。第一呢,我们需要了解Objective-C的对象模型,然后才能去理解消息发送的过程,再然后再去了解下Runtime都能干什么,毕竟如果一个技术没有落地的应用,那它就没啥价值了。这篇文章基于objc4-723源码进行分析,GitHub有一个可调试库,<a href="https://github.com/RetVal/objc-runtime">地址</a>。
<!-- more --></p>
<h1 id="简介">简介</h1>
<p>Runtime是什么?官方文档第一段就给出了答案。</p>
<blockquote>
<p>The Objective-C language defers as many decisions as it can from compile time and link time to runtime. Whenever possible, it does things dynamically. This means that the language requires not just a compiler, but also a runtime system to execute the compiled code. The runtime system acts as a kind of operating system for the Objective-C language; it’s what makes the language work.</p>
</blockquote>
</description>
<pubDate>Mon, 14 May 2018 17:48:48 +0000</pubDate>
<link>
/%E5%9F%BA%E7%A1%80%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84</link>
<guid isPermaLink="true">/%E5%9F%BA%E7%A1%80%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84</guid>
</item>
<item>
<title>iOS UI开发捷径读书笔记一——基础概念理解</title>
<description><p>最近读了《iOS UI开发捷径–利用Interface Builder高效、优雅地开发UI》这本书。感觉受益匪浅,记录下自己在书里面学到的东西。这里只写自己学到的新知识,并不介绍一些简单的IB知识,想要具体学习,请买书自己学习。
<!-- more --></p>
<h2 id="和interface-builder有关的几个重要概念">和Interface Builder有关的几个重要概念</h2>
<p>下面介绍几个和IB有关的概念,学习下平常经常用,但是不了解的概念。</p>
<h3 id="bundle">Bundle</h3>
<p>这个我们在平常工作中应该经常用,比如创建IB的时候,还有获取资源路径的时候:</p>
</description>
<pubDate>Mon, 22 Jan 2018 09:57:39 +0000</pubDate>
<link>
/UI%E5%BC%80%E5%8F%91%E6%8D%B7%E5%BE%84%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0</link>
<guid isPermaLink="true">/UI%E5%BC%80%E5%8F%91%E6%8D%B7%E5%BE%84%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0</guid>
</item>
<item>
<title>迟来的2017总结</title>
<description><p>2017年过去了,今天是2018年01月10日,终于有时间整理一下过去,展望一下未来了。年初给自己定了几个目标,但是那时没有写东西的习惯(虽然现在也没有),现在回想起来已然不记得什么了。只记得一个大概就是多读书,多写总结。然而并没有达到。只能说一年的时光又被我浪费掉了。从这篇文章开始,以后每周要写一篇文章了。对未来的展望,依然是多读书,多写文章。因为,读书是一个输入的过程,而写作是个输出的过程。希望自己写的都是自己实践过的,不写软文。先不展望未来了。先回忆下过去吧。下面从工作、生活、学习三方面做下总结。
<!-- more --></p>
<h2 id="工作">工作</h2>
</description>
<pubDate>Wed, 10 Jan 2018 11:25:50 +0000</pubDate>
<link>
/%E8%BF%9F%E6%9D%A5%E7%9A%842017%E6%80%BB%E7%BB%93</link>
<guid isPermaLink="true">/%E8%BF%9F%E6%9D%A5%E7%9A%842017%E6%80%BB%E7%BB%93</guid>
</item>
<item>
<title>读Objective-C高级编程笔记一——引用计数</title>
<description><p>最近读了《Objective-C高级编程》这本进阶书:
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/1503026660.png" alt="Objective-C高级编程" />。
这本书有三章,我们先来介绍第一章。可以从下图看下第一章的整体结构。
<img src="https://nightwish.oss-cn-beijing.aliyuncs.com/1503025584.png" alt="内存管理" />。
<!-- more -->
本篇是第一篇,来写下iOS的内存管理,其实iOS的内存管理无论是ARC还是MRC都是通过引用计数来管理的。每个对象都有一个<code class="highlighter-rouge">retainCount </code>的属性。当一个对象的<code class="highlighter-rouge">retainCount </code>为0,就说明没有地方使用该对象了,可以释放了。
我们先看MRC,再看ARC,因为ARC其实是建立在MRC之上的,只是是编译器在合适的地方代替我们插入了内存管理的代码。</p>
</description>
<pubDate>Tue, 15 Aug 2017 23:27:57 +0000</pubDate>
<link>
/%E8%AF%BBObjective-C%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E7%AC%94%E8%AE%B0%E4%B8%80-%E5%BC%95%E7%94%A8%E8%AE%A1%E6%95%B0</link>
<guid isPermaLink="true">/%E8%AF%BBObjective-C%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%E7%AC%94%E8%AE%B0%E4%B8%80-%E5%BC%95%E7%94%A8%E8%AE%A1%E6%95%B0</guid>
</item>
<item>
<title>UIKit Dynamic Tutorial</title>
<description><p>这是一篇翻译自Raywenderlich上的文章,<a href="https://www.raywenderlich.com/50197/uikit-dynamics-tutorial">原文</a>。
<!-- more --></p>
<h2 id="whats-uikit-dynamic">What’s UIKit Dynamic</h2>
<p> iOS7鼓励我们设计出一个物理动态的效果,这个听起来是一个很艰巨的任务。但是苹果爸爸已经为我们提供了一些非常好用的东西,就是UIKit Dynamics和Motion Effects。</p>
<ul>
<li>UIKit Dynamics 是一个被整合的UIKit中的完整物理引擎。它允许你通过添加一些重力,附件(弹簧),力等行为来创建感觉真实的效果。你只管定义界面元素采用的物理特征,其他的就交给UIKit Dynamics。</li>
<li>Motion Effects 就是你创建的一些行为,比如上面提到的那些重力,附件等等的东西。
当把这两个用在一起时,将会很自然的响应自己的行为。
<h2 id="getting-started">Getting started</h2>
<p>我们新建一个项目,然后在viewController里面加上下面的代码:</p>
</li>
</ul>
</description>
<pubDate>Thu, 15 Jun 2017 23:14:22 +0000</pubDate>
<link>
/UIKit-Dynamic-Tutorial</link>
<guid isPermaLink="true">/UIKit-Dynamic-Tutorial</guid>
</item>
<item>
<title>学习动画系列---寄宿图</title>
<description><p> 上一篇学习了下<code class="highlighter-rouge">CALayer</code>的概念,者一篇学习下<code class="highlighter-rouge">CALayer</code>的内部属性,我们先来解释下什么是寄宿图。在上一篇中,我们通过<code class="highlighter-rouge">CALayer</code>类创建了一个蓝色的背景图层,如果他仅仅是展现一个单调的颜色,~~那我还学他干啥?~~其实它还可以包含一张图片,它里面包含的图我们就叫寄宿图。这个名字太奇怪了。估计是翻译的问题吧。
<!-- more --></p>
<h1 id="contents属性">contents属性</h1>
<h2 id="contents">contents</h2>
<p> <code class="highlighter-rouge">CALayer</code>有个<code class="highlighter-rouge">contents</code>属性,这个属性被定义为id类型,但是可不要被定义为id类型迷惑,如果给<code class="highlighter-rouge">contents</code>属性赋的值不是CGImage,那么他就是一个空白的layer。</p>
</description>
<pubDate>Tue, 22 Nov 2016 11:54:36 +0000</pubDate>
<link>
/%E5%AD%A6%E4%B9%A0%E5%8A%A8%E7%94%BB%E7%B3%BB%E5%88%97-%E5%AF%84%E5%AE%BF%E5%9B%BE</link>
<guid isPermaLink="true">/%E5%AD%A6%E4%B9%A0%E5%8A%A8%E7%94%BB%E7%B3%BB%E5%88%97-%E5%AF%84%E5%AE%BF%E5%9B%BE</guid>
</item>
<item>
<title>学习动画系列---理解CALayer</title>
<description><p> 好长时间没写东西了,由于刚换了工作,一直在忙于熟悉业务,和一些新业务的开发,没有时间对自己的技术进行修行。这段时间终于闲下来了,可以找些自己感兴趣的东西来好好学习下了。最近在学习些高级动画,在gitbook上面看到一个<a href="https://www.gitbook.com/book/zsisme/ios-/details">iOS核心动画高级技巧</a>,阅读了下,写的是一些动画的基础。毕竟学东西,我们要从基础学起嘛。你连1+1都不会算,怎么学习数学,这是一个道理。好吧,我有些跑题了😀。我们平常用的UIView可以实现一些基础的动画,但是有时产品🐶要做一个非常牛逼的动画时,我们就有些傻眼了。这里就需要用到一个高级东西了,在我们iOS里面叫Core Animation,下面我们就来系列学下这个牛逼的东西。先来学习下比UIView高级些的东西,这个东西就叫CALayer。
<!-- more --></p>
<h1 id="calayer和uiview">CALayer和UIView</h1>
<p> iOS中所有的view都是<code class="highlighter-rouge">UIView</code>派生来的。<code class="highlighter-rouge">UIView</code>可以处理触摸事件,可以支持绘图,可以做仿射变换(其实就是旋转和缩放),<code class="highlighter-rouge">UIView</code>还可以做简单的类似于滑动,或者渐变动画。</p>
</description>
<pubDate>Mon, 21 Nov 2016 15:42:49 +0000</pubDate>
<link>
/%E5%AD%A6%E4%B9%A0%E5%8A%A8%E7%94%BB%E7%B3%BB%E5%88%97-%E7%90%86%E8%A7%A3CALayer</link>
<guid isPermaLink="true">/%E5%AD%A6%E4%B9%A0%E5%8A%A8%E7%94%BB%E7%B3%BB%E5%88%97-%E7%90%86%E8%A7%A3CALayer</guid>
</item>
<item>
<title>理解属性</title>
<description><p>属性是Objective-C的一项特性,用于封装对象内的数据。OC对象常会把需要的数据保存为实例变量,实例变量一般通过存取方法(这里的存取方法指的就是setter/getter方法)来访问实例变量。其中setter方法用于写入变量的值,getter方法用于读取变量的值。大家也许已经使用过属性这一概念了,不过大家未必会知道其中所有的细节,而且还有很多与属性有关的麻烦事。这里将会告诉大家有哪些问题可以用属性解决,并指出其中所体现出的关键特性。
<!-- more -->
在一个描述个人信息的类中,我们可能会存放人名,生日,地址等内容,我们可以在类的.h文件中声明一些实例变量,如下图所示:
<span><img src="\images\理解属性\1.png" /></span>
以前写过java或者C++的人应该比较熟悉这种写法,可以定义实例变量的作用域,然而编写OC却很少这样做。这种写法的问题是:对象布局在编译器就已经固定了,只要碰到<code class="highlighter-rouge">_firstName</code>变量的代码,编译器就把其替换为“偏移量”,这个偏移量是“硬编码”,表示该变量距离存放对象的内存区域的起始地址有多远。这样做目前看来没有什么问题,但是如果又增加了一个实例变量,如下图所示:
<span><img src="\images\理解属性\2.png" /></span>
原来表示<code class="highlighter-rouge">_firstName</code>的偏移量现在却指向了<code class="highlighter-rouge">_dateOfBrith</code>了,把偏移量硬编码于其中的那些代码都会读到错误的值,下面这个表可以演示这个过程,请自己对比加入<code class="highlighter-rouge">_dateOfBrith</code>这一实例变量之前和之后的内容布局,其中假设指针为4个字节(64位系统为8个字节)
<span><img src="\images\理解属性\3.png" /></span>
如果代码使用了编译期计算出来的偏移量,那么在修改类定义后必须重新编译。否则就会出错,比如:某个代码库中的代码使用了一份旧的类定义,如果和其相链接的代码使用了新的类定义,那么运行时就会出现不兼容的现象。各种变成语言都有应对这个问题的方法。OC的做法是,把实例变量当做一种存储偏移量的“特殊变量”,交由类对象保留。偏移量会在运行期查找,如果类的定义改变了,那么存储的偏移量也就变了,这样无论何时访问实例变量,总是使用正确的偏移量。甚至可以在运行期向类中新增实例变量,这就是稳固的“应用程序二进制接口”(ABI),ABI定义了许多内容,其中一项就是生成代码时所应该遵循的规范,有这种稳固的ABI,我们就可以在“class-continuation分类”中或实现文件中定义实例变凉了,所以说,不一定要在接口中把全部实例变量都声明好,可以将某些变量从接口的public区段移走,以便保护和类实现有关的内容。
这个问题还有一种解决方法,就是尽量不要直接访问实例变量,而是通过存取方法来做。虽说属性最终还是通过实例变量来实现,但它却提供了一种简洁的抽象机制。你可以自己编写存取方法。在OC的编码风格中,存取方法有着严格命名规范,正因为这种规范,所以OC才能根据名称自动创建存取方法,这是<code class="highlighter-rouge"><span class="k">@property</span></code>就派上用场了。
在对象接口的定义中,可以使用属性,这是一种标准写法,能够访问封装在对象里的数据。因此可以把属性当成一种简称。其意思是说:编译器会自动写出一套存取方法,用以访问给定类型中具有给定名称的变量例如下面这个类:
<span><img src="\images\理解属性\4.png" /></span>
对于该类的使用者来说,上述代码写出来的类和下面这种写法等效;
<span><img src="\images\理解属性\5.png" /></span>
要访问属性,可以使用点语法,在纯C种,如果想访问分配在栈上的struct结构体里面的成员,也需要用类似的语法,编译器会把点语法转换为对存取方法的调用,使用点语法的效果和直接调用存取方法相同。因此使用点语法和直接调取存取方法之间没有丝毫的差别。
然而属性还有更多的优势,如果用了属性,编译器会自动编写访问这些属性所需的方法,这个过程叫做“自动合成(autosynthesis)”,需要强调的是,这个过程编译器在编译器执行,所以编译器里面看不到这些“合成方法”的源代码。除了生成方法代码外,编译器还会向类中添加适当的实例变量,并且在属性名前加上下划线,以此作为实例变量的名字,在前面的例子中,会生成两个实例变量,分别是<code class="highlighter-rouge">_firstName</code>和<code class="highlighter-rouge">_lastName</code>,也可以在类的.m文件中使用<code class="highlighter-rouge">@sythesize</code>语法来指定实例变量的名字,如下图:
<span><img src="\images\理解属性\5.png" /></span>
不过一般不推荐这么做,因为所有人都用一套方案,那么写出来的代码大家都看的懂。
如果不想令编译器自动合成存取方法,则可以自己在.m文件中实现,如果只是实现了一个,那么另一个还是编译器来合成。还有一种方法可以阻止编译器自动合成存取方法,就是使用<code class="highlighter-rouge">@dynamic</code>关键字,它会告诉编译器不要自动创建实现属性所用的实例变量,也不要为其创建存取方法,而且在编译器访问属性代码时,即便发现没有定义存取方法,也不会报错,它相信这些方法可以在运行期找到。比如说:如果从CoreData框架中的NSManagedObject类里继承一个子类,那么就需要在运行期动态创建存取方法,继承NSManagedObject时之所以这样做,是因为子类的某些属性不是实例变量,其数据来自后端数据库中。</p>
<pre><code class="language-objective-c">@interface Person : NSManagedObject
@property NSString *firstName;
@property NSString *lastName;
@end
</code></pre>
<p>```objective-c
@implementation Person
@dynamic firstName,lastName;
@end</p>
</description>
<pubDate>Mon, 29 Feb 2016 15:42:49 +0000</pubDate>
<link>
/%E7%90%86%E8%A7%A3%E5%B1%9E%E6%80%A7</link>
<guid isPermaLink="true">/%E7%90%86%E8%A7%A3%E5%B1%9E%E6%80%A7</guid>
</item>
<item>
<title>iOS9的适配</title>
<description><p>iOS9升级后相信很多人都是项目报错,因为项目要升级iOS9,从网上看了很多教程,就这篇教程还是比较全的,分享给大家,顺便自己记录下。网址是<a href="http://www.cocoachina.com/ios/20151016/13715.html">整理 iOS 9 适配中出现的坑(图文)</a>。</p>
</description>
<pubDate>Mon, 18 Jan 2016 13:46:30 +0000</pubDate>
<link>
/iOS9%E7%9A%84%E9%80%82%E9%85%8D</link>
<guid isPermaLink="true">/iOS9%E7%9A%84%E9%80%82%E9%85%8D</guid>
</item>
<item>
<title>iOS视图控制器的生命周期</title>
<description><p> 我们去面试很多时候都被问到视图控制器的声明周期,下面我们着重来讲解下视图控制器的声明周期。
<!-- more --></p>
<h2 id="了解重要的三个函数">了解重要的三个函数</h2>
</description>
<pubDate>Wed, 14 Oct 2015 14:20:25 +0000</pubDate>
<link>
/iOS%E8%A7%86%E5%9B%BE%E6%8E%A7%E5%88%B6%E5%99%A8%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F</link>
<guid isPermaLink="true">/iOS%E8%A7%86%E5%9B%BE%E6%8E%A7%E5%88%B6%E5%99%A8%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F</guid>
</item>
<item>
<title>iOS事件响应机制</title>
<description><p> 本文着重讲解iOS事件的传递机制,如有错误或者有意见不同者,欢迎指出讨论。</p>
</description>
<pubDate>Wed, 07 Oct 2015 14:20:25 +0000</pubDate>
<link>
/iOS%E4%BA%8B%E4%BB%B6%E5%93%8D%E5%BA%94%E6%9C%BA%E5%88%B6</link>
<guid isPermaLink="true">/iOS%E4%BA%8B%E4%BB%B6%E5%93%8D%E5%BA%94%E6%9C%BA%E5%88%B6</guid>
</item>
<item>
<title>如何用类族模式隐藏实现细节</title>
<description><p> 类族是一种很有用的模式,可以隐藏“抽象基类”中的实现细节。这里的抽象基类是指在这个类中只提供接口,并没有提供实现细节,通常是子类重写这个接口,来实现其中的细节。OC中的系统框架普遍应用这个模式。下面我们来举个例子,iOS中有个UIButton的类,想要创建一个按钮,需要调用下面这个方法:
<!-- more --></p>
</description>
<pubDate>Thu, 24 Sep 2015 14:20:25 +0000</pubDate>
<link>
/%E5%A6%82%E4%BD%95%E7%94%A8%E7%B1%BB%E6%97%8F%E6%A8%A1%E5%BC%8F%E9%9A%90%E8%97%8F%E5%AE%9E%E7%8E%B0%E7%BB%86%E8%8A%82</link>
<guid isPermaLink="true">/%E5%A6%82%E4%BD%95%E7%94%A8%E7%B1%BB%E6%97%8F%E6%A8%A1%E5%BC%8F%E9%9A%90%E8%97%8F%E5%AE%9E%E7%8E%B0%E7%BB%86%E8%8A%82</guid>
</item>
<item>
<title>理解对象等同性</title>
<description><p> 根据“等同性”来比较对象是一个非常有用的功能。不过,按照==操作符比较,未必是我们想要的结果,因为该操作比较的是两个指针的本身,而不是其所指的对象。我们应该使用NSObject协议声明的<code class="highlighter-rouge">isEqual</code>方法来判断两个对象的等同性。一般来说,两个类型不同的对象总是不相等的。某些对象提供了特殊的等同性判断方法,如果知道了两个对象都属于同一个类,那么久可以使用这种方法了。我们用下面的代码做例子:
<!-- more --></p>
</description>
<pubDate>Thu, 17 Sep 2015 14:20:25 +0000</pubDate>
<link>
/%E7%90%86%E8%A7%A3-%E5%AF%B9%E8%B1%A1%E7%AD%89%E5%90%8C%E6%80%A7</link>
<guid isPermaLink="true">/%E7%90%86%E8%A7%A3-%E5%AF%B9%E8%B1%A1%E7%AD%89%E5%90%8C%E6%80%A7</guid>
</item>
<item>
<title>对象内部应该如何访问实例变量</title>
<description><p> 在上一篇中,我们讲解了一些属性的特质,接下来我们讲下访问实例变量的问题,在对象之外访问实例变量时,总是应该通过属性来做,那么在对象内部访问实例变量又该如何呢?OC的开发者一直在激烈的讨论这些问题。有的人认为,无论什么情况都应该使用属性访问实例变量,也有人说通过属性访问和直接访问应该搭配着使用。除了集中特殊情况外,在这里建议大家在读取实例变量时采用直接访问,在设置实例变量时通过属性来做。
<!-- more -->
请看下面这个类:</p>
</description>
<pubDate>Thu, 10 Sep 2015 15:26:23 +0000</pubDate>
<link>
/%E5%AF%B9%E8%B1%A1%E5%86%85%E9%83%A8%E5%BA%94%E8%AF%A5%E5%A6%82%E4%BD%95%E8%AE%BF%E9%97%AE%E5%AE%9E%E4%BE%8B%E5%8F%98%E9%87%8F</link>
<guid isPermaLink="true">/%E5%AF%B9%E8%B1%A1%E5%86%85%E9%83%A8%E5%BA%94%E8%AF%A5%E5%A6%82%E4%BD%95%E8%AE%BF%E9%97%AE%E5%AE%9E%E4%BE%8B%E5%8F%98%E9%87%8F</guid>
</item>
<item>
<title>属性的特质</title>
<description><p> 最近读了Effective Objective-C。开篇就当做一篇笔记吧。在使用属性的时候,我们需要注意一个问题,就是属性的各种特质(attribute)设定也会影响编译器所生成的存取方法,下面这行代码,相必大家都很熟悉了。这行代码就指定了三项特质。
<!-- more --></p>
</description>
<pubDate>Thu, 03 Sep 2015 14:36:23 +0000</pubDate>
<link>
/%E5%B1%9E%E6%80%A7%E7%9A%84%E7%89%B9%E8%B4%A8</link>
<guid isPermaLink="true">/%E5%B1%9E%E6%80%A7%E7%9A%84%E7%89%B9%E8%B4%A8</guid>
</item>
</channel>
</rss>