-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
875 lines (581 loc) · 91.5 KB
/
atom.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
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Straybird's Blog]]></title>
<link href="http://straybirdzls.github.io/atom.xml" rel="self"/>
<link href="http://straybirdzls.github.io/"/>
<updated>2015-08-31T20:03:32+08:00</updated>
<id>http://straybirdzls.github.io/</id>
<author>
<name><![CDATA[Straybird]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[新生活]]></title>
<link href="http://straybirdzls.github.io/blog/2015/08/13/newlif/"/>
<updated>2015-08-13T21:48:01+08:00</updated>
<id>http://straybirdzls.github.io/blog/2015/08/13/newlif</id>
<content type="html"><![CDATA[<p>最近这个月发生了换了工作,换了租的房子,换了室友,也换了一种生活状态。</p>
<!-- more -->
<p>先来说说工作吧,组里的人陆陆续续多了起来,每个人都有鲜明的特点,每个人对待事物有自己的理解和处理方式,也渐渐地感觉到一个毫无特点的人在职场中是不会胜出的。</p>
<p>最近在带动跟进一个项目的时候发现了自己很多的缺点和不足</p>
<ol>
<li>对于项目的预估和期望结果没有一个提前的判断和认知,自己没有这个能力的时候,也没有主动通过沟通去获取这些信息</li>
<li>对于项目过程中会遇到的一些东西没有进行考虑,以致于很多东西到最后才开始考虑</li>
<li>信息收集时没把大家拉到一个水平线上,没提供一种统一的方式去采集,以致于花费很多时间在沟通,数据统计和反馈再沟通上</li>
<li>对于一些事物习惯性没看法,没意见,以致于开会时没核心骨,经常被带走</li>
<li>在领导在质疑和催进度时,没去思考和改进,也不会去推动组员</li>
<li>不懂老板心,不明白他想看到的是什么,思考力,反馈力偏弱</li>
<li>拖延,不愿与不熟悉的人主动沟通开始暴露出来了</li>
</ol>
<p>但也渐渐能看到自己的一些改进了</p>
<ol>
<li>开始去计划一些东西了</li>
<li>开始明白工作方式,做事情的方式是相当重要的,在当职场菜鸟时,闷头做事也许可以有比较快的沉淀,但等到一定的阶段就会是绊脚石了,因为不可能说一件事情不需要任何的配合</li>
</ol>
<p>总得来说,虽然工作上越到一些困难,觉得很多东西跟以前不一样了,但是相信可以让自己成长。现在马上要开始跟进一个新项目,现在已经开始能感觉到自己在某些方面又有逃避心理了,发现很多时候拖延并不是真正的因为懒,而是因为对于某件事情有些恐惧,没把握,就习惯将其留到最后一刻找一种方式糊弄过去。成长就是要与自己固有的行为作斗争,加油~! 需要改进的地方有太多,一个一个来。</p>
<p>再说说生活吧,其实现在的生活大部分也就是工作了,只不过现在的工作会带动我的生活习惯,比如不会太晚睡了,早上按时起了,每天都会吃早餐,想想这些都是很不错了。早上起来的时候有时候都感觉到一种力量,一种激情,而这在之前很长一段时间都没感觉到,那时候似乎就是在混着,早上起来也觉得很没劲,晚上有时还不按时睡觉,想想这些都是好事吧,生活态度比以前积极了。反正我也不是一个生活乐趣比较足的人,多花点时间工作,改进自己,一定是好事。</p>
<p>最后说说室友吧,感觉还是不能跟关系太好,太熟,老同学这种一块住,因为这种会让人比较随意,然后越来越懒,因为彼此太熟悉,很多时候就不会注意。但现在就感觉不一样了,虽然也比较熟,但之前没有很多生活中实质性地交互,现在就会努力地一块去建立一些东西,维护一些形象,挺好的。</p>
<p>嘿嘿,综合起来,现在的一切都在往更好的方向发展,加油~!</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[一件难过的事]]></title>
<link href="http://straybirdzls.github.io/blog/2015/07/18/sad/"/>
<updated>2015-07-18T20:07:52+08:00</updated>
<id>http://straybirdzls.github.io/blog/2015/07/18/sad</id>
<content type="html"><![CDATA[<p>写出这个题目的时候,觉得似曾相识,然后突然想起小学时候经常写“一件难忘的事”。这是一件难过的事,也许也难忘,但我希望我可以尽快忘掉。</p>
<!-- more -->
<p>其实昨天这件事在心中还只是一点小火花,可晚上睡觉的时候,本来很困很困,不知道为啥突然又想到这件事,然后就像发酵了一样,越想越难过,难过到快不能忍。于是拿出手机,想了想也不知道给谁说,怎么去开这个口,但必须找个墙洞,否则就有种过不去的感觉,于是打开无密,编辑了一个秘密,编辑好之后却又开始觉得发出去似乎不太好,当事人们看到了肯定会一眼辨别出来,虽然我很想去问问他们,但还是明白这种问题的确是不应该说出口的。犹豫了很久,把未发出的秘密复制给了以前的头,现在我们不在一个生活圈了,然后她也一定明白我在说什么。很意外,她居然很快回复了,大半夜12点我还想着她一定已经休息了。她安慰了我很久,虽然对事实本身是没有任何可以有所为的地方,但聊着聊着竟然慢慢觉得豁然开朗起来,睡意也渐渐回来了。</p>
<p>然而今天每每想到这件事,虽然不会像昨晚那样连呼吸都不畅快了,但依然有点隐隐地难受,对于事实的本身不能接受,也完全无法猜测到事实的背后有没有发生过什么,或者是不是完全没有发生过什么,是不是自己误解了什么。</p>
<p>也许还是太年轻吧。很多事情都看不明白。</p>
<p>也许读者你看得一头雾水,但这件事我无法在公共场合说,只是想记录下现在心情。也许多年以后我已经无法回想起来这件事情,就当让自己见识见识时间的力量吧。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[胡言乱语]]></title>
<link href="http://straybirdzls.github.io/blog/2015/07/10/zatan/"/>
<updated>2015-07-10T16:57:16+08:00</updated>
<id>http://straybirdzls.github.io/blog/2015/07/10/zatan</id>
<content type="html"><![CDATA[<p>有一段时间没更新博客了,其实好几次写了个开头,但没有办法继续下去,最终只好作罢。</p>
<!--more-->
<p>今天在讲完iOS Code Coverage的transfer之后,心中突然飘来很久没有过的失落感,甚至都不知道失落什么,也许是两年多的一个圈要画完了,不知道该怎么挪到另一个,心中的期待渐渐地被一些焦虑所替代。</p>
<p>以前总觉得迎向新生活总是好的,现在新生活还没来临,自己就已经完全明白,新生活不见得比现在好,却总有一种力量告诉自己,该move on了。其实想move on的心早就有了,但一直没有足够的动力去做,所以一直拖着拖着,所以这次心里开始着急了,很担心拖着拖着又把决心拖没了。与着急一起生长的还有担忧,担忧找不到合适的房子,合适的室友,担心对新生活新环境的难以融入,甚至担心发现一切又没变的时候的心安与恐惧。</p>
<p>只能感叹,人生真是一个难题,都说人活着是为了自己开心,可是如何能让自己开心才是关键的,我知道荒废时间不能让我开心,我知道碌碌无为不能让我开心,可我并不知道什么能让我开心。也许在人生这个关节,我能做的就只是硬着头皮,走下去,不管前方是什么,也不管能获得什么,会失去什么,就是一种成功了。</p>
<p>很多人谓我坚强,其实脆弱起来真是没底,有时候自己都无法理解,怎么脆弱成这样子了,都不如从前了。可我也知道每一拨脆弱都会给我带来新的力量,因为总能够克服过去,而克服过去了当前的一切就变得没那么难。</p>
<p>嗯,不说了,默默的脆弱,然后默默的坚强。</p>
<p>–纯胡言乱语</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[倒数第三个青年节]]></title>
<link href="http://straybirdzls.github.io/blog/2015/05/04/young/"/>
<updated>2015-05-04T19:09:11+08:00</updated>
<id>http://straybirdzls.github.io/blog/2015/05/04/young</id>
<content type="html"><![CDATA[<p>昨天在和妈妈一起去看望二爹爹的路上,碰到了一个小学好朋友的妈妈。之后妈妈就说前些天收拾东西的时候还看到了我小学时候的同学录,那时候的感情都多么地好,为什么现在都没有来往了,甚至连她们在哪里干什么都毫不知情。</p>
<!-- more -->
<p>今天正值青年节,也是我人生中的倒数第三个青年节,突然对妈妈嘴中的同学录之类的产生了强烈的兴趣,于是乎开始翻箱倒柜地找了起来,找到了好多宝贝,小学时候的同学录,高中时候的日记、周记,大学时候的日记等等。</p>
<p>翻开小学同学录,第一个留言的就是文章开头提到的好朋友,看来这个就是那时最好的朋友了,可是我得通过妈妈才知道她现在在干些什么。满本同学录几乎每一页都写着勿忘我,可惜很多名字我都不记得了,有些记得名字的也忘记长什么模样,知道现在在哪的寥寥无几,保持联系的那更是一个都没有。我不禁感叹,人真的就是这样吗,一段时间一个生活圈,读书时代,工作时代,家庭时代,认识的人很多很多,但最终能记得模样的也许都能数得出来。看到同学录上每个人都认真地写下自己的梦想,真的很想问问你们的梦想都实现了吗?也突然很想知道自己当时在别人的同学录上都写了些什么呢,梦想又是什么呢。</p>
<p>翻开高中时的周记和日记,有欢乐,有痛苦,有纠结,这些记录印证着那时候生活的印记。高中三年也许很枯燥,但这些记录让我觉得那时候的生活特别真实,也特别用心和用力。有跟好友扔“纸条”嬉皮笑脸或者互诉心情;有纠结玩与乐之间的平衡,那时候真是痴迷于乒乓球,甚至还以乒乓球拍为第一人称写了一篇周记;有纠结于朋友间的真诚或者不合,那时候的友谊也许并不弱于爱情,大家都是真心地交着朋友,甚至会嫉妒你对她比对我好;也有很搞笑的写了一篇周记,说自己想当一个男孩,很想很想,结果老师的评语只有一句话“我没有这个能力帮你“;但看到一篇周记,我却触感良多,那篇周记说的是家里的猫跑到我的床上产了4只小猫,结果有一只夭折,可能存在于世界上的时间只有几个小时甚至几分钟,然后我就开始感触生命,中间就有这么一段:</p>
<blockquote><p>我想:生命是短暂的,也是长久的。有意义的生命短暂也好,但无意义的生命不管有多长久也终究时无意义,那是无法改变的事实。上次看了一篇文章,里面说人人都在寻找一件东西,那就是快乐,但我想仅仅为了快乐而活是不够的,每个人都有自己的目标,有自己的信念,否则我们何必去奋斗呢!想清楚了这些问题,我的生活也变得充实起来,我也算明白了自己为什么而活!</p></blockquote>
<p>我无法知道当时我写下这些文字的时候到底是什么心情,但现在看到这些,突然发现原来这些年困扰自己的问题,时常问自己的问题,原来在高中时代就曾经找到过答案。有人说历史总是惊人地相似,绕圈子,却止步不前,人又何尝不是呢,有时候我们会觉得自己成长了,但有时候回过头看看倒还真不一定成长了,有些曾经可以轻松克服的问题现在克服不了了,有些曾经的困惑现在依然困惑,但也许这些也都是不可避免的,生活上坡下坡,我们谁都无法保证一直上坡,而且也许有些时候,下坡是为了更好的上坡。</p>
<p>接着翻开大学时候的日记,刚开始的几乎与高中时的一样,对于适应新生活速度很缓慢,不知道怎么去交朋友,看到别人都是认识3天2天就手拉手干这干那的,一方面觉得羡慕,一方面就觉得这样交朋友是不是太轻浮了,然后就开始怀念之前时代的朋友们。我就发现自己几乎每踏入一次新的环境,都会循环一遍这种过程,因为我从来都只是记录自己的心情,没想过要去改变,就一直这么慢热的过来了。自己还是习惯于待在舒适区,对于苦恼会努力地告诉自己一切都会过去,最终都会迎刃而解,而不会想着去尝试改变。大学日记也充分反应自己在自我管理方面的弱势,很多篇日记都是在规定自己什么时候起床,什么时候睡觉,什么时候锻炼身体,但每次都是坚持不了多久,到现在依然如此。一直以来都把次归结于,我喜欢自由,不喜欢被束缚,可是一个人如果连健康的生活习惯都难以坚持,还谈什么自由,自由是一种心灵的状态,而认真生活是对生活本身的一种尊重,是对自己作为成年人的负责,两个八杆子打不着关系的东西混在一起只能说是找了一个太隐藏的借口。大学时候的另一个调调就是保研这个目标了,这个实现了,但现在的我只能说这是在那个时候最好的选择,但如果重来,我大概不会把这个定为目标了。</p>
<p>我想这是我青年节最好的礼物了吧,平凡的世界中晓霞说“爱情于我是初见端倪,却已使我一尘如洗”,我借用一下,“生活于我是初见端倪,却已让我尝到苦涩之处”。看看曾经走过的路,再想想现在的生活现在的状态,我想我一定可以更好的走未来的路。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Javascript学习2]]></title>
<link href="http://straybirdzls.github.io/blog/2015/04/12/javascript2/"/>
<updated>2015-04-12T14:54:51+08:00</updated>
<id>http://straybirdzls.github.io/blog/2015/04/12/javascript2</id>
<content type="html"><![CDATA[<p>这篇接着上篇,不过有些迟到了。随着Facebook React Native的开源,现在Javascript颇有点“王道”的意思了,一定要将学习坚持下去!这篇主要说说Javascript中的面向对象。</p>
<!-- more -->
<h3>对象</h3>
<p>ECMAScript中把对象定义为:无序属性的集合,其属性可以包含基本值,对象或者函数。其没有类的概念,每个对象都基于一种引用类型创建的,这种引用类型可以是原生的,也可以是自定义的。所以在javascript中其对象跟一般oo语言中的区别还是蛮大的。</p>
<p>ECMAScript中给对象定义了2种(内部)属性,数据属性和访问器属性。数据属性包含一个数据值的位置,在这个位置可以读取和写入值。数据属性有4个描述其行为的特性:[[Configurable]],[[Enumerable]],[[Writable]],[[Value]]。要修改属性默认的特性,必须使用Object.defineProperty()方法。访问器属性不包含函数值:他们包含一对getter和setter函数(不是必需的)。使用Object.getOwnPropertyDescriptor()可以取得给定属性的描述符。</p>
<h3>创建对象</h3>
<p>创建对象的最简单的方式就是使用new操作符或者字面量法,其如下:</p>
<pre><code>//new操作符
var person = new Object();
person.name = "hao";
//字面量法
var person = {name:"hao"};
</code></pre>
<p>这很明显的一个缺点就是会有大量的重复代码,为了解决这个问题,就有很多种设计模式,在javascript里用的最多的就是工厂模式,构造函数模式,原型模式以及组合使用构造函数与原型模式了,当然也还有其他很多的模式,不过它们基本都是对构造函数模式或者原型模式的变种。这里我只谈下最基本的。</p>
<h4>工厂模式</h4>
<p>工厂模式抽象了创建具体对象的过程,考虑到在ECMAScript中无法创建类,开发人员就发明了一种函数来封装以特定接口创建对象的细节。</p>
<pre><code>function createPerson(name,age)
{
var o = new Object();
o.name = name;
o.age = age;
o.sayName = function() {
console.log(this.name);
};
return o;
}
var person = createPerson("hao",26);
</code></pre>
<p>工厂模式解决了创建相似对象时代码重复的问题,但没有解决对象识别的问题。</p>
<h4>构造函数模式</h4>
<p>在ECMAScript中,任何函数都可以当作构造函数,只要使用new操作符。但按照管理,构造函数应该使用大写字母开头,而非构造函数则用小写字母开头,以做区分。</p>
<pre><code>function Person(name,age)
{
this.name = name;
this.age = age;
this.sayName = function() {
console.log(this.name);
}
}
var person = new Person("hao",26);
</code></pre>
<p>使用new操作符时,会经历4个步骤:1)创建1个新对象 2)将构造函数的作用域赋给新对象3)执行构造函数中的代码 4)返回新对象。使用构造函数模式时,生成的对象都会有一个constructor属性,上例中,该属性指向Person。但是检测对象类型,还是使用instanceof操作符会更好。</p>
<pre><code>console.log(person instanceof Object);
console.log(person instanceof Person);
</code></pre>
<p>使用构造函数模式有一个问题就是函数对象不是共享的,每一个实力都会产生自己的函数对象,但实际上它们是可以共享的,为了解决这个问题,可以将函数定义转移到构造函数外部,如下</p>
<pre><code>this.sayName = sayName;
function sayName(){
console.log(this.name);
}
</code></pre>
<p>这样带来的问题就是会有很多的全局函数,既破坏了封装性,也让全局作用域名不副实-全局作用域中定义的函数实际上只能被某个对象调用。</p>
<h4>原型模式</h4>
<p>在1中,我们提到过每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和当法。</p>
<pre><code>function Person(){
}
Person.prototype.name = "hao";
Person.prototype.age = 26;
Person.prototype.sayName = function() {
console.log(this.name);
};
var person = new Person();
</code></pre>
<p>原型模式创建出来的对象,属性和方法都是共享的,即原型对象的。默认情况下,原型对象都会自动获得一个constructor属性,这个属性包含一个指向prototpye属性所在函数的指针。当创建一个新对象时,该对象内部包含一个指针(内部属性),指向构造函数的原型对象。虽然无法直接访问[[Prototype]],但可以通过isPrototypeOf()方法来确定对象间是否存在这种关系。ECMAScript5中也新增了一个方法Object.getPrototypeOf().</p>
<pre><code>console.log(Person.prototype.isPrototypeOf(person)); //ture
console.log(Object.getPrototypeOf(person) == Person.prototype); //true
</code></pre>
<p>当访问对象属性时,会首先搜索实例对象中的,没搜索到则搜索其原型对象中的。值得注意的是可以通过对象访问原型中的值,但不能重写。如果往实例中增加与原型中相同的属性,则会屏蔽原型中的。可以通过hasOwnProperty来检测属性是否来自于实例。而in操作符则不论属性属于实例还是原型中时都会返回true。</p>
<pre><code>var person1 = new Person();
var person2 = new Person();
person1.name = "test";
console.log(person1.hasOwnProperty("name")); //true
console.log("name" in person1); //true
console.log(person2.hasOwnProperty("name")); //false
console.log("name" in person2); //true
</code></pre>
<p>可以给原型对象直接赋值,但是会破坏constructor属性(不会影响instanceof操作符)。所以如果需要直接赋值时,最好自己将constructor属性补上(下面有示例)。</p>
<p>原型模式可以弥补构造函数模式不方便共享实例函数的不足,但是对于属性而言,则共享就不是很合理了。对于那些包含基本值的属性而言,可以用同名属性覆盖,但对于引用类型的属性而言,问题就比较突出了。</p>
<pre><code>function Person() {
}
Person.prototype = {
constructor : Person,
friends : ["hao"]
};
var person1 = new Person();
var person2 = new Person();
person1.friends.push("test");
console.log(person1.friends); //[ 'hao', 'test' ]
console.log(person2.friends); //[ 'hao', 'test' ]
</code></pre>
<h4>组合使用构造函数模式与原型模式</h4>
<p>通过上面的构造函数模式和原型模式的分析,我们知道,对于属性而言,我们一般不需要共享,最好使用构造函数模式,而对于函数而言,一般需要共享,最好使用原型模式,所以就有了组合模式,现在也是被用的最多的一种模式,这里也就不多做说明了。</p>
<p>本想这次也记录一下继承的,不过发现内容有点多,这个就放到下回了。</p>
<h3>参考文献</h3>
<p>JavaScript高级程序设计(第3版)</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Javascript学习1]]></title>
<link href="http://straybirdzls.github.io/blog/2015/03/22/javascript1/"/>
<updated>2015-03-22T22:50:36+08:00</updated>
<id>http://straybirdzls.github.io/blog/2015/03/22/javascript1</id>
<content type="html"><![CDATA[<p>随着近些年来nodejs的火爆,Javascript终于在一等语言公民中站稳了脚,其实Javascript并不是一门简单的脚本语言,其也有很多高级特性,而且其中很多概念跟其他语言有相当大的差别。Javascript算是由三部分组成:ECMAScript+DOM+BOM,后两者都是为Web前端服务的,而ECMAScript则定义了其语法。</p>
<!-- more -->
<h3>类型</h3>
<p>Javascript中有6种数据类型,其中5种基本数据类型Undefined, Null, Boolean, Number, String。1种复杂数据类型Object。其中Undefined类型只有一个指,即特殊的undefined,变量定义没有初始化都会默认赋为此值, Null类型也只有一个值,即null(空指针对象),如果定义的变量准备用来保存对象,则最好将其初始化为null。typeof操作符可以帮忙确定变量的类型。值得注意一点的是:对于尚未声明过的变量,只能执行一项操作,即使用typeof操作符检测其数据类型(会返回”undefined”)。</p>
<h3>执行环境与作用域链</h3>
<p>执行环境是Javascript中最为重要的一个概念,其定义了变量或函数有权访问的其他数据,决定了它们各自的行为。有全局执行环境(web浏览器中为windows)和函数执行环境。当代码在一个环境中执行时,会创建变量对象的一个作用链域,其作用是保证对执行环境有权访问的所有变量和函数的有序访问,作用链域的前段,始终都是当前执行环境的变量对象。Try,catch语句的catch块以及with语句可以在作用域链的前端新增一个变量对象。相当值得注意的是Javascript中没有块级作用域。</p>
<h3>引用类型</h3>
<p>在ECMAScript中,引用类型是一种数据结构,用于将数据和功能组织在一起。其与类看起来很像,但它们并不是相同的概念。引用类型的值(对象)是引用类型的一个实例。原生的引用类型有如下几种:Object,Array,Data,RegExp,Function,基本包装类型(Boolean,Number和String)- 每当读取一个基本类型值时,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些当法来操作这些数据,单体内置对象(Global对象和Math对象)。</p>
<h3>函数</h3>
<p>Javascript很有意思的一部分就属函数了,如上所说,函数类型是一种引用类型,也即是说函数实际上是Object,而函数名仅仅是一个包含指针的对象。基于这个原因,Javascript中没有函数重载(申明同名函数,结果是后面的函数覆盖了前面的函数)。在Javascript中函数还有一些特性。</p>
<ol>
<li>参数传递全部是值传递</li>
<li>函数有2个内部属性,<code>arguments</code>和<code>this</code>,其中<code>arguments</code>代表着参数,所以进行参数传递时,对于参数的个数无所谓,<code>arguments</code>除去参数列表外,还有一个<code>callee</code>属性,其是一个指针,指向拥有这个<code>arguments</code>对象的函数,在写递归时,用<code>callee</code>属性是最安全的;而<code>this</code>是函数据以执行的环境对象。</li>
<li>因为函数只是<code>object</code>,所以其也有属性,<code>length</code>和<code>prototype</code>,其中<code>length</code>表示函数希望接收的命名参数的个数,对于引用类型而言,<code>prototype</code>是保存它们所有实例方法的真正所在。</li>
<li>每个函数都包含两个非继承而来的方法,<code>apply()</code>和<code>call()</code>,它们的区别就是参数传递的方式不一样,<code>apply</code>使用数组传递,而<code>call</code>则直接传递,两个方法的第一个参数都是运行函数的作用域</li>
<li>函数分函数声明和函数表达式两种定义方式,函数声明有函数提升的能力(调用在前,声明在后),函数表达式的方式则是定义了匿名函数</li>
<li>支持闭包,是指有权访问另一个函数作用域中的变量的函数。也就是说当函数结束放回时,其执行环境已经销毁,但是活动对象还没销毁,所以在闭包中依然可以访问。</li>
<li>可以通过<code>(function() {...})()</code>的方式来模仿块级作用域。</li>
</ol>
<p>这里只是记录一些学习笔记,对于Javascript我也只是初入茅庐,Javascript中另外一个很有意思的就是其对象和其原型实现了,这个下次再记录了。</p>
<h4>参考文献</h4>
<p>JavaScript高级程序设计(第3版)</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[敏捷初体验]]></title>
<link href="http://straybirdzls.github.io/blog/2015/03/10/agile/"/>
<updated>2015-03-10T22:32:36+08:00</updated>
<id>http://straybirdzls.github.io/blog/2015/03/10/agile</id>
<content type="html"><![CDATA[<p>公司转入敏捷已经有一段时间了,我们组实践开始得比较早,算起来有1个多月了,从最开始尝试的新鲜感,到第一次开iteration planning meeting开了4个小时时的无奈,再到开始体验到敏捷的好处,一切看似曲折却又无比的顺其自然。当然对于敏捷,我这也只是初体验而言。</p>
<!-- more -->
<p>刚开始敏捷的时候,我们时常会被各种各样的meeting,繁杂的流程搞得很崩溃,觉得导致效率低下,整天这么开会,还怎么敏捷?讨论的时间都可以把事情做完了!但渐渐地开始觉得每个meeting都有其意义和用处,如果你觉得开会耽误了效率,那说明这个会本身开得有问题。</p>
<p>首先说说iteration planning meeting,个人认为po在其中的角色非常重要,po在开会之前需要做很多的准备,包括写backlog,包括从组员处了解当前的需求等等,如果po没有做好这些准备,会极大地影响到会议的效率。会议的第一步就是要对backlog进行rank,这个如果po前期准备做好了,则很快就能够让大家达到共识,之后的user story打分是会议比较好玩的一部分,因为这个时候owner需要向组员阐述清楚任务到底是什么,然后通过打分讨论最后达成共识,这个过程一开始的时候大家的打分可能会很不一致,但越往后出现大家打分都一样的情况会越来越多,我觉得这一过程一方面可以培养owner表达任务的能力,另一方面就是小组里的每一个人对一项任务都可以处于同样的理解层面。之后的建立task等等不细说了。这个meeting需要详尽地确定在这个iteration中每个人的task是什么,需要多长时间完成等等。个人觉得也是每个人对于一个iteration的承诺。</p>
<p>再来说说daily standup meeting,我们组把这个meeting放到了一天工作差不多结束的时候,需要说三个问题,1.我今天做了什么,完成度是多少2.我明天要做什么,3.我遇到了什么困难,一开始我们的困难仅仅局限于需要别人帮助的问题,然后会后自己私下讨论,后来我们又加了一点,就是当完成度小于100%的时候需要说明原因,我觉得这个很好,这相当于强制我们对一天的工作进行反省,除了理清楚今天做了什么之外,我们也要思考为什么任务没有100%完成,阻挡因素在哪,应该怎么处理,然后在做第二天的plan的时候也会更加仔细地考虑。</p>
<p>最后说说review,retrospective and demo meeting了,这个meeting就是对一个iteration的工作进行总结和反省了。review会看每一个user story,task完成的情况,retrospective就是思考在上一个iteration中有什么做得好的地方和不好的地方,demo就是展示一下做的成果。这个meeting就是一个总结的meeting,这也是我们兑现在plan meeting中承诺的meeting,这也是我们反省思考并且争取在下一个itreation中改善自己不足的meeting。</p>
<p>也许有人会说,敏捷的meeting似乎不是这么分的呀?我觉得敏捷是活的,不是死的,敏捷提出了一些很好的概念,而怎么去实践,则可以根据自己组里的情况和大家讨论的结果,比如我们小组就决定将上一个itreation的结束meeting和下一个itreation的开始meeting放在一块开,总结完之后就开始指定下一个iteration的计划了,我们觉得这样效率更高,更符合我们的实际情况,再比如一开始我们的daily standup meeting是在早上开,说昨天做了什么,今天要做什么,后来发现经常会忘记昨天做了什么,况且我们也不是特别在意这个,所以我们才改为了快下班的时候开,也觉得效果很好。</p>
<p>还有人会说,敏捷也有很多问题啊?对,我也承认敏捷有很多问题,但既然是问题,那就有解决方案。比如突然来了urgent task怎么办?个人对此的回答是,如果这个task不影响整个iteration的plan,那么可以默默地处理掉,但如果影响了,那么就需要联系po,让他决定,如果po决定不做,则联系scrum master,让他去交涉,如果po决定做,那么同时还要挪出一些priority比较低的task,在敏捷中,po和scrum master都是很关键的角色,遇到问题的时候不要犹豫,该寻求帮助的时候就要果断出手。再比如一个iteration结束了,很多task没完成?这个就是在最后的iteration结束的meeting中需要考虑的了,为什么没做完?是对自己的估计失误还是做task时对一些临时的task的处理有问题等等,这样做下一个iteration plan的时候就要多加考虑了。我们很难保证我们每次都能完成所有的任务,但是再一次一次的迭代中,我们对于任务估计与实施的理解会更准确。</p>
<p>最后说说我个人从敏捷中得到些什么吧。 <br/>
1. 由于自己拖延症很严重,所以这种有计划有deadline的形式帮助了我不少, 这种感觉跟给你一个task,然后就放任不管的感觉很不一样 <br/>
2. 让我养成了反省和思考的习惯 <br/>
3. 我清楚地了解了各个组员在做什么,这样遇到相关问题可以很方便地请教或借鉴 <br/>
4. 学会了时间管理,这算是1的附属物吧,因为deadline摆在那,每天也需要汇报自己做了啥,所以必须对自己的时间和task进行有效地管理</p>
<p>当然,我也没有成为敏捷的脑残粉,其可能不是适用于所有的团队和所有的人,我自己也觉得敏捷走起来也没有那么容易,很多时候反而会成为“敏捷”的绊脚石,当然了,个人还是相信再一次又一次的实践中,一切应该都会变得更有效率,而我们也必将通过不断的改善,让敏捷造福于我们。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[叔叔]]></title>
<link href="http://straybirdzls.github.io/blog/2015/02/25/shushu/"/>
<updated>2015-02-25T10:02:21+08:00</updated>
<id>http://straybirdzls.github.io/blog/2015/02/25/shushu</id>
<content type="html"><![CDATA[<p>昨天又被叔叔上了政治课,大概就是说他们大人现在深刻认识到了我们家族这边对子女教育的误点,个个都是智商高情商低,混社会硬伤太多,这些其实大部分也不是教育所致,而是生活环境所致,我们生活的地方日子太简单,一日一日,一年一年就这么过来,学习在进步,知识在增长,也许心智也在成熟,可惜混社会的能力一点都没增长。</p>
<!-- more -->
<p>听完之后我感触挺多的,其实并不是因为叔叔说的道理有多么深刻,其实很多问题很久之前自己就认识到了,我猜测我的那些兄弟姐妹们肯定也已意识到了,只不过愿不愿意改变以及有没有勇气和能力去跟长久以来的习惯做斗争才是事情能不能换个方向发展的转折点。真正让我觉得感触多的是叔叔对待事情的态度。</p>
<p>在四十多,即将迈入五十的年龄,叔叔的身上充满了力量,在2年不到的时间内拿到了注册税务师,并在年终一项考试中作为我们市唯一一个进入了全省前二十名,秒杀了无数985,211的80后和90后们。我是看着叔叔怎么去对待这些考试的,注册税务师有6门考试,难度很大,在周六周末去武汉照顾老婆孩子的时候,每天都是早起锻炼看书做饭,生活中除了做饭锻炼身体以及亲情沟通以外的所有时间都拿来复习备考,在工作日的情形就更不得而知了。叔叔并不是只是重视这些考试,他时时刻刻都在观察检讨,学习新知识。在发现工作中缺失excel技能的时候,会向晚辈讨教,并花上2天时间学习训练,从此工作事半功倍;在发现晚辈在社交中都存在很多问题的时候,开始自学心理学,观察分析教育,与此同时定下下一个目标:拿到心理咨询师的证书,改变自己的同时帮助教育晚辈;发现身体处于亚健康状态的时候,果断弃掉小车换以自行车和腿代步,每天坚持锻炼几个小时的身体;发现家里双方都是忙工作无人会做饭时,每到一处都虚心讨教各种厨艺,现在做的饭无人不夸。这种事情太多太多,在写下的过程中,我看到了叔叔身上的诸多特质,而这些特质都是相当珍贵难得的。</p>
<p>有时候我自己会想,在我即将迈入五十岁的时候我会有怎样的人生态度,我能保持一颗向上的心吗,有资格去教育引导晚辈了吗,想着想着就会开始惭愧,在二十多岁正青春年上的年龄,我都很难去做到这些事情,我总是会纠结在人到底是应该把自己擅长的事情做好还是应该努力去改变自己,不过现在得到了答案,努力改变自己并不会影响将擅长的事情做好,因为虽然人的精力是有限,也不可能时时刻刻地都在做自己擅长的事情,而且人生面临的路和事情都是千奇百怪,把自己固有在擅长的事情之中只能说是逃避和懦弱,人如果无法战胜自己,那终究就是失败的。嗯,以后只问自己,能把自己擅长的事情做好并且努力地扩展更多的领域吗?</p>
<p>人生在世短短几十年,来的时候不带什么,走的时候也带不走什么,想想唯一可以做的那大概就是在活着的时候努力绽放,努力精彩,克服一个又一个的困难,战胜一个又一个的恐惧,永不停步吧。争取在四十多岁的时候能有叔叔那样的斗志,但在现在就努力去拥有叔叔那样的行动力吧!</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Ruby,就是这么任性(1)]]></title>
<link href="http://straybirdzls.github.io/blog/2015/02/06/ruby/"/>
<updated>2015-02-06T22:00:23+08:00</updated>
<id>http://straybirdzls.github.io/blog/2015/02/06/ruby</id>
<content type="html"><![CDATA[<p>由于工作需求,最近开始学习ruby了,其实前段时间也学过一些,但因为久未用之,再捡起来发现已经是忘得差不多了。而且由于之前学习的时候只是在机械的学习一些语法,对这门语言并没有多么深刻的领悟,这次学习的时候心态就不一样了。</p>
<!--more-->
<h4>ruby的哲学</h4>
<p>说哲学,也许太过大了一点,但在ruby的世界观,任何问题都没有唯一的解决方案,其身上处处透露着不羁。正如最近看到的将语言比作国家的笑话中,ruby被比喻为“法国,以为自己很厉害,但其实没人鸟”,颇有点自命清高的意思。但随着近几年ruby on rails的火爆,ruby也算是翻身了,但硬伤还在,那就是在大型项目的性能一直有待考证,以及太过自由的语法给团队协作也带来了困难。相对而言,python则表现更加优良,其一个问题,一个解决方案的哲学更加适合于团队之间的协作。</p>
<h4>自由的语法</h4>
<p>这次重新接触ruby,是从公司YES框架开始的。一开始遇到了好多坑,也咒骂这门语言,太灵活,太动态,但慢慢学习下去才知道其带来的好处。当然我也不认为有些自由的语法是多么的必要,但对于ruby工程师而言,这些也许就是这门语言吸引他们的一部分原因。</p>
<ul>
<li>ruby的每一行代码不需要以分号结束,会自动判断。一行写不完的情况下,而且结尾处是操作符等可以被判断出来的,那不需要特殊处理,直接第二行接着写就可以了;如果结尾处不好判断,则加上\即可。</li>
<li>方法调用既可以加括号,也可以不加括号。这是把我坑的很惨的一个语法,有时候都不是很好分辨是方法调用还是参数定义。个人感觉,方法带参数的时候还是加括号吧。</li>
<li>如果说ruby一直是灵活的自由的,那这一个也许就是其唯一的不灵活不自由吧,在ruby总,局部变量要以小写字母或下划线开头,全局变量以$开头,实例变量以@开头,类变量以@@开头,常量和类/模块名以大写字母开头。其中类变量使用前必须被初始化。</li>
<li>写属性方法的定义是以属性=(值)的方式的,这是我见过的第一门这么定义的语言,以=结尾的确是相当直观。其实只要定义以=结尾的函数,就可以将其用于表达式的左侧。</li>
<li>类方法的定义有三种方法,self.方法名,类名.方法名,class <<self然后再定义。这很好地体现了ruby的哲学。</li>
<li>每个函数都有返回值,如果没有显式的定义,那就是函数最后一行执行的结果。其实不仅仅是函数,在ruby中,表达式也是有返回值,比如if等,它们的返回也是最后一行执行的结果。这颇有种给表达式赋予了生命的感觉。</li>
<li>数组的访问中不用担心越界,越界直接返回nil,越界赋值则直接中间的全部赋为nil。负数下标表示从后往前的顺序,这一点我个人觉得很人性,也很方便。还可以通过range来访问,其中..表示包含尾,…表示不包含尾。</li>
<li>除了=以外,?和!也可以作为函数定义的后缀,其中?表示这是查询函数,!则表示会修改对象本身,谨慎使用。</li>
<li>在ruby中,如果想要一个行参接受多个参数,那太容易了,只需要加上*就可以了</li>
<li>block的两种方式有两种,{}以及 do…end,其中后者优先级低于前者。block可以直接跟在函数后面,在函数中通过yield就可以调用到block。block在ruby中很关键也很强大。</li>
</ul>
<p>关于ruby,我也还在学习中,所以很多地方的见解不见得对。这个系列我会接着写下去,因为ruby这门语言的确有很多可圈可点的地方,我就边学边总结吧。预计后面会写无处不在的block,模块与mixin,强大的动态性,ducking type等,当然也会继续总结语法。第一篇就暂时到这里了,真实情况是肚子里没货了,赶紧学习去了!</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[语言的哲学]]></title>
<link href="http://straybirdzls.github.io/blog/2015/01/29/language/"/>
<updated>2015-01-29T20:54:33+08:00</updated>
<id>http://straybirdzls.github.io/blog/2015/01/29/language</id>
<content type="html"><![CDATA[<p>最近在看”programming ruby”这本书的时候,被序言深深吸引,也解答了我心中最近一直存在的一些疑问。</p>
<!-- more -->
<p>回想起,从大学到现在,接触过的语言和技术,不分先后地包括:汇编,C, C++, Java, Javascript, python, Objective-c, ruby, ruby on rails, mysql, node.js, coffeescript, html/css, php, swift, JSP,编译原理, R, Tweak, Cycript, 密码学,http/https等等。有些在在校期间学习的,有些是工作中的需求,有的是自我督促学习的。这一年,在自我和被逼学习的过程,心中的疑问确是越来越多,为什么要学习这么多不同的语言?似乎也派不上用场?甚至,为什么这个世界上要有这么的不同却又如此相似的语言,如果全部来个大统一,不是所有人都开心?</p>
<p>第一次看到有人这么正式地说到此问题,是在看编译原理公开课的时候,为什么需要这么多不同的语言?教授的解答是,不同的平台有不同的需求,比如涉及到硬件,就需要c这种方便与底层交互的,涉及到强大的数据处理,就需要R语言这种的。当时看到这的时候,发现,其实这些我也都明白,也承认有一些主流的语言,主流的平台确实有其存在的道理,但为什么还是有一些新语言不断的出现,关键是他们看起来跟已有的语言区别并没有那么大呢?</p>
<p>在不断学习放弃的过程中,我逐渐认识到,其实学会什么语言,什么技术都是次要的,关键是你可以拿你学到的东西去做点什么,而不断的去学习一些新东西,一方面是日后需要的时候有备无患,而另一方面则是技术更新换代速度太快,是应该局限于当前,还是应该开放视野,拥抱变化呢?</p>
<p>对,变化,我们每个人在学习语言技术的时候,很容易机械地去学习一些表面上看起来一样的语法,无非就是控制流程,面向对象,翻来覆起几个词说得都要烂掉,而其实真正应该关注的是语言和技术的背景是什么样的,是基于一种什么样的需求的产物,而不应该是语言本身。回想起我自己学过的这些东西,其实每一样都是一些特殊时代,特殊需求的产物,汇编和C就不用说了,python和ruby,一直以来对比良多,我之前也一直苦于该学习哪个,但其实两种语言本身的哲学就不一样,根据需求,根据个人喜好,一切都有答案,想起最开始接触objective-c的时候,被它的语法搞得很崩溃,但竟慢慢地喜欢上这么语言,惊叹于如此强大的runtime实现,而一开始的时候一直都不认为那些类,方法等面向对象的概念与c++有什么不同,实在是有点对不住这两门语言,而再慢慢被这门语言吸引的时候,苹果却又推出了swift,一直有点抵触,觉得之前花那么大精力学的是不是白学了,可事实上是,这个时代就是变化的,每个平台,都种技术都在努力完善更新,应该用下心来去了解新技术,了解技术背后传达的思想和哲学。我们知道的永远都是浅显的,我们所学习的也永远只是一角,最近学node.js才知道,原来javascript已经可以脱离浏览器运行,但自己却还活在javascript是前端脚本语言的世界里。技术的世界又怎么可能有个大统一?大统一何来进步?这天下都合久必分,分久必合,还指望技术的世界一成不变?</p>
<p>这篇文章叫语言的哲学,其实已经完全偏题了,开始想表达的跟最终写出来的竟如此差别之大。其实最近的感觉和ruby书的序言告诉我们的,千言万语汇成如下几句:
这个世界是不会停止变化的,技术的世界更加如此,如果想要在技术的世界中行走的更远,那么就用心去了解技术背后传达的思想和哲学,与之为友,而不是机械地灌输。先用心踏实地用已有的知识汇聚成面,做点实事,然后保持open heart 以及 keep learning。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[自省小记]]></title>
<link href="http://straybirdzls.github.io/blog/2015/01/24/zixing/"/>
<updated>2015-01-24T11:11:08+08:00</updated>
<id>http://straybirdzls.github.io/blog/2015/01/24/zixing</id>
<content type="html"><![CDATA[<p>转眼间就24号了,拖拖拉拉,最终还是没能在第三周写下一篇博客,回想起近日的种种,深刻地觉得该反省一下了。</p>
<!-- more -->
<p>最近工作上由于处于换组的阶段,所以总感觉有些混乱。ios组总有一些事情需要处理,而自己又想早点参与到devops的项目,却一直处于学习期,搞得每天的站立会议都会让自己觉得没能出上什么力,却还需要花时间来培训自己。在工作中也看到了自己的惰性,经常会拿两边的事情来搪塞自己,塘塞别人,其实真正算下来,两边组的事情都没能处理得很好。</p>
<p>近日也开始思考,自己到底想要工作中的一些什么样的特质,也特别佩服“处于什么角色,就拿出什么状态”的一些人们。</p>
<p>雷厉风行,我想这四个字足以表达我对工作状态的一种期望。现在的我总是会觉得不愿意做那些边边角角,特别琐碎的事情,所以当遇到一些问题的时候,只愿意扮演其中找出问题关键点的角色,剩下的事情就不愿管了。还有现在在工作中也越来越淡定,碰到“escalation”,一番研究发现没什么成果之后,都能淡定地等着,直到邮件催命符,才愿意去继续努力一把,然后周而复始,弄上个一个多月。前几天,又遇到一个这种状况,抓到问题的关键点之后,就想撒手不管了,把问题向gloria描述了一番之后就装作与自己无关了,直到gloria的一封邮件出来之后,才开始慢慢地感觉到自己的不是,以及“雷厉风行”的做事态度应该是什么样。</p>
<p>首先,拖拖拉拉永远只是自己的借口,网速不行,邮箱挂了,这些统统都只是借口。其次,遇到事情,应该扮演什么样的角色,心里应该给自己一个预期,能不能独立地让人信任地去完成一件事情?再次,觉得这个很烦,那个也很烦,请问什么不烦?每一件小事中都能学到东西,一封邮件不同的人写出来可能完全是另一番风景。</p>
<p>我想,雷厉风行这四个字我的理解还非常地粗浅,但可不可以先从以下几点做起? <br/>
1. 邮件来了,马上处理,不清楚的地方可以立马回复提出疑问,不要说等到什么时候再处理,其实那就有点double work的感觉,至少邮件就需要读两次。如果有不可阻挡力,则给自己定一个deadline,并标示,什么时候之前必须处理。 <br/>
2. 每天分出一个固定的时间去集中处理遇到的issue,需要找人交流的,立马找人交流,不要等 <br/>
3. 每天standup会议之前,要好好总结,必须是针对明天要完成什么这一样,一定要谨慎思考,然后第二上早上到的时候将其温习一遍,并为今天的时间做出安排</p>
<p>团队精神,昨天的乌镇之行让我感触良多,在团队中应该怎么发挥自己的力量,应该怎样去面对困难,想扮演什么样的角色,这些都是自己的主动力可以解决的。有些人可以一直鼓励大家,有些人却容易影响团队的志气,你想成为哪个?</p>
<p>热爱生活,积极主动,每个人都无法拒绝阳光,有些人就可以让阳光一样,照耀别人,如果无法做到这些,至少是不是应该不要当作乌云,遮挡别人的阳光?工作中雷厉风行,生活中阳光灿烂,其实身边有很多这样的榜样,可不可以多观察多学习?放下自己的固执,放下自己以为的很重要的一些东西,用心去体验一切,一切都会变成另一番景色。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[一件小事]]></title>
<link href="http://straybirdzls.github.io/blog/2015/01/12/littlething/"/>
<updated>2015-01-12T21:15:27+08:00</updated>
<id>http://straybirdzls.github.io/blog/2015/01/12/littlething</id>
<content type="html"><![CDATA[<p>今天听朋友讲了一件小事,听了之后感触良多,又觉得可笑又觉得可悲。</p>
<!-- more -->
<p>朋友是一位单身女青年,这里就称为z女吧,有一天有人给她介绍了一个单身男青年,这里称为c男。两人通过微信成为了好友。开始有一搭没一搭的聊了起来,开始基本上没聊起来,因为c男发消息的时候z女没看到,看到了回复了c男又可能没能及时回复,经过这么几次之后,终于在一天晚上算是多聊了几句。从那一天之后,c男基本上每天晚上都会找z女聊天,但每次都是要到z女说自己要睡觉了,否则都不会停下来。这么几天之后,有时候z女就不会及时回复了,因为晚上的时光并不多,吃了晚餐,看看书,看看电视,并不是每天都想花特别多的时间去聊天,有时候也是因为微信的消息没有及时看到,有时候聊着聊着被别的事情打岔了,就直接没回复了,尽管如此,c男基本还是会每天说一下。又这么过了2~3天,之后的那天正好周末,c男早上,下午又各发了一条信息,等到z女看到/有时间回复的时候已经距下午的信息过了几个小时。她回复了一下,结果傻眼了,得到提示:“你与对方不是好友,。。。”。z女觉得很莫名其妙,想着会不会是误操作了,就加了好友,过了一会c男同意了并说,能不能下周见一面,z女就问是不是特意删了好友。c男说,觉得合适就继续,不合适不想当备胎,请见谅。z女解释了一下为什么有时候消息没及时回,以及觉得并不想很短时间内就判断一个人合适不合适,对于备胎自己也是毫无兴趣,但针对删好友这个行为只能觉得那就确定两人不合适。然后商量好,z女就删了c男的好友。本以为故事这里结束了,结果没想到,第二天,c男又发了加好友的请求,并说后悔了,还来不来得及,说其实自己也是个好人,昨天误会你了,昨天自己也失常了。故事到这里,我知道的也结束了,也不知道z女还会不会再同意c男的好友请求。</p>
<p>其实这只是一件很小的事情,但却让我很感慨,特别是针对“备胎”,“好人”这两种说辞,深深让我感觉到,社会和校园的差别。到了现在这个年龄,似乎大家都是直奔目标,没有耐心拉长线去好好了解双方,特别害怕付出得不到回报,特别想很快地把一切都定下来。而据我所知,按照z女的性格,以往如果是这种情况,她肯定会直接跟c男说,不是每天都有时间聊天,可不可以换个时间,自己是慢热型的,希望可以放缓点节奏,可现在她也不会直接这么说,因为觉得说不出口,似乎觉得很伤人心,也觉得显得特别矫情,而针对删好友的行为,她肯定会骂个狗血淋头,两人直接谈掰。但现在她竟也觉得没什么好生气,似乎也在慢慢接受这个社会现实化的感情,相反觉得这个行为正好让她觉得两人不合适,也好。</p>
<p>回想起校园中的恋情,似乎最常见的就是“死缠烂打”了,男生管女生回不回应,就一门心思对你好,可以在一起,那太好了,不能,那我祝福你,但还是对你好。女生也一样,答应男生的时候,根本不会考虑家境,合不合适等这些婚姻中很重要的因素,只会考虑“我是不是喜欢他?”,就这么简单。</p>
<p>说着说着似乎有点矫情了,也许是自己的心态也开始慢慢变化了,开始觉得人生中没有谁一定是谁的谁,觉得感情这东西特别玄乎,结婚生子之后主要也不是靠这个维续了,觉得很难再去open heart,很难再去毫无顾虑了吧。嗯,不过虽然如此,却还是憧憬,憧憬愿得一人心,白首不分离,憧憬一起去闯荡未来的生活,憧憬在这个变化莫测的世界依然保持童真。</p>
<p>嗯,有人说过,童真并不是躲在象牙塔中什么都不懂,而是认清了世界真实的模样,却依然能不忘初心。你能够做得到吗?</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[iOS学习笔记3]]></title>
<link href="http://straybirdzls.github.io/blog/2015/01/06/ioslearning3/"/>
<updated>2015-01-06T20:35:21+08:00</updated>
<id>http://straybirdzls.github.io/blog/2015/01/06/ioslearning3</id>
<content type="html"><![CDATA[<p>最近又重新看了下斯坦福公开课的课程,也看了下effective objective-c这本书,还杂七杂八看了一些东西,课程和书还都没有看完,但已觉得学到了不少新的知识点,或者是以前没有意识到的知识点。这里记录一下。</p>
<!--more-->
<h3>语法糖</h3>
<p>Objective-c中引入了语法糖,让NSArray,NSDictionary等Foundation里集合的语法显得简捷,但需要主要的是,语法糖也有一些需要注意的地方。</p>
<ul>
<li>创建的语法糖只对mutable对象有,对immutable没有</li>
<li>不能增加nil的对象,会抛出exception,而使用非语法糖时,则会截断至nil</li>
<li>subclass不能用,不过类簇也不推荐subclass,这个我在<a href="http://straybirdzls.github.io/blog/2014/11/16/xianche/">此文</a>中也提到过</li>
</ul>
<h3>Event响应机制</h3>
<p>这一部分基本算是翻译自苹果的<a href="https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40009541-CH1-SW1">官方文档</a>。</p>
<p>ios中的事件分为3种,1.触摸事件 2.传感器事件 3.远程控制事件。当事件发生时,UIKit会创建对应的event并将其放入app的event队列中。事件在被响应需要经过层层传递,首先UIApplication会从event队列中选出top event进行分发,通常会发给UIWindow,最终传递给一个初始对象进行处理。
对于触摸事件,初始对象被称为hit-test view,而找到其的过程称为hit-testing。hit-testing通过hitTest:withEvent:返回touch发生的view,其内部通过递归地调用pointInside:withEvent:来得到hit-test view.</p>
<p>而对于传感器事件和远程控制事件,则交给first-responder对象处理。</p>
<p>responder对象是是指可以响应event的对象。UIResponder是所有responder对象的基类, UIApplication,UIView,UIViewController等都是responder对象。first-responder是被指定为最先响应event的对象,可以通过<code>canBecomeFirstResponder</code>和<code>becomeFirstResponder message</code>将object设置为first-responder。当first-responder无法响应event时,其会传递给next responder直到UIWindow,UIApplication。</p>
<p>对于Touch event,hit-test view即为first-responder,而其响应链的响应顺序如下: <br/>
1. viewj将event传递其view controller中view hierarchy的superview,直到topmost view <br/>
2. topmost view将event传递给其view controller <br/>
3. view controller将event传递给其topmost view的superview <br/>
1-3循环,直至根view controller,最终至UIWindow直至UIApplication。</p>
<h3>消息机制</h3>
<p>在iOS中,我们知道消息是通过runtime在实现表中进行查找来实现响应的,除了通过正常的方式创建方法外,runtime机制还会通过几下步骤进行消息传递:</p>
<ol>
<li>动态方法解析,<code>ResolveInstanceMethod/ResolveClassMethod</code>,这是最后将方法加入IMP表中的机会,其中可以通过<code>class_addMethond</code>等加入对应的IMP,假如完之后会再进行一次消息的派送。因为这个的真正实现时将方法加入IMP表中,所以isResponseToSelector中是会查找到这其中的实现的。@dynamic是使用动态方法解析的一个很典型的例子,其告诉编译器property的setter和getter会在运行时提供。</li>
<li>快速消息转发:可以通过<code>ForwardingTargetForSelector</code>来实现,只能将消息转发给一个对象</li>
<li>标准转发,通过实现<code>-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector</code>和<code>-(void)forwardInvocation:(NSInvocation *)anInvocation</code>这两个方法进行转发。NSMethodSignature是方法签名,为什么要有这个呢?那是因为selector其实只是一个字符串,从它并不能知道参数的类型和返回值的类型,而方法签名实际上是用来描述参数的类型和返回值的类型的。也就是说,相同的返回值与参数的所有selector的签名其实是一致的。而Objc运行时要根据对象返回的这个签名来抓取参数,然后才会调用<code>- (void)forwardInvocation:(NSInvocation *)anInvocation</code>这个方法。</li>
</ol>
<p>不得不说runtime真的好强大。</p>
<h3>KVO实现</h3>
<p>KVO用到了isa swizzling,以下是从别人文章里引用的,可惜很抱歉,我忘记具体时哪篇文章。</p>
<blockquote><p>当某个类的对象第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的 setter 方法。 <br/>
派生类在被重写的 setter 方法实现真正的通知机制,就如手动实现键值观察那样。这么做是基于设置属性会调用 setter 方法,而通过重写就获得了 KVO 需要的通知机制。当然前提是要通过遵循 KVO 的>属性设置方式来变更属性值,如果仅是直接修改属性对应的成员变量,是无法实现 KVO 的。 <br/>
同时派生类还重写了 class 方法以“欺骗”外部调用者它就是起初的那个类。然后系统将这个对象的 isa 指针指向这个新诞生的派生类,因此这个对象就成为该派生类的对象了,因而在该对象上对 setter 的调用就会调用重写的 setter,从而激活键值通知机制。此外,派生类还重写了 dealloc 方法来释放资源。</p></blockquote>
<h3>安全相关</h3>
<ul>
<li>class-dump的工作原理:因为 obj-c的动态特性导致 obj-c的二进制代码中会保留类名和方法名,所以可以用 otool 得到这些信息,而class-dump所做的就是把otool -ov得到的信息组织成结构更清晰的信息输出</li>
<li>通过在xcode中设置<code>-Wl,-sectcreate,__RESTRICT,__restrict,/dev/null</code>可以给输出的二进制文件中增加<code>__RESTRICT/__restrict section</code>来防止dylib注入,更多的信息,可以参见<a href="http://bbs.iosre.com/forum.php?mod=viewthread&tid=432">这篇文章</a></li>
</ul>
<h3>一些容易犯的错误</h3>
<ul>
<li>NSDictionary/NSArray这种里面只能存储对象,不能存储普通的变量,这个在写代码时很容易忘记</li>
<li>NSNotification Center 会通过_unsafe_unretain指向observer,所以不再需要的时候一定要记得remove,否则会带来意料不到的crash</li>
</ul>
<p>这一篇比较杂七杂八,因为本身就是平时学习笔记的一些归纳总结,方便自己温习查看。</p>
<h2>参考文献</h2>
<p><a href="https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40009541-CH1-SW1">苹果官网EventHandling</a> <br/>
<a href="http://bbs.iosre.com/forum.php?mod=viewthread&tid=432">防止tweak依附,App有高招;破解App保护,tweak留一手</a></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[2014年终总结]]></title>
<link href="http://straybirdzls.github.io/blog/2014/12/30/summary/"/>
<updated>2014-12-30T21:50:14+08:00</updated>
<id>http://straybirdzls.github.io/blog/2014/12/30/summary</id>
<content type="html"><![CDATA[<p>还有1天,2014年就结束了,今天也赶回热闹,写写年终总结。回想起2014,总有种恍如隔梦的感觉,过年离家的情景还历历在目,现在却已经抢好了今年过年回家的车票。</p>
<!-- more -->
<h3>工作</h3>
<p>截止到今天,我已经工作了快600天,我还清晰地记得工作的每一个阶段。嘿嘿,我们姑且就忽略我文章题目中的2014吧。</p>
<ul>
<li>2013年4月15日,第一天入职,对人生中的第一份工作充满了憧憬,认识了一块培训的小伙伴。培训的日子虽然不轻松,但是很充实,很快乐。对待培训很认真,认真地学习课程,认真地回家复习准备考试,认真而愉快地在西湖的11个景点留下自己和小伙伴们的身影。也认识了之后很久一段时间一起上下班的贴心小伙伴。</li>
<li>2013年6月14日,不知道这个确切的日子记的对不对,分组结果出来了,非常心碎,自己的1/2/3选择都抛弃了自己,进入了当时被我列为最不想去的三个组之一。chase叔叔非常nice地跟我解释为什么让我进入这个组,心中暗暗告诉自己,还是要努力。</li>
<li>2013年6月17日,入组第一天,组里没有cube了,跟同组的另外一个小伙伴一起共享一个办公室,非常地爽。见到了p姐,也见到了gloria。p姐带领我们认识组员,然后根据个人兴趣让我们做相应的方向。gloria第一次见的时候是她带着我去见jin哥哥,说我跟着他做,很简单的一句话,然后大部分时候她跟jin哥哥闲扯,好不欢乐。那时候对于“领导”还是有点小怕的。</li>
<li>2013年6月20日,2天的xyati培训结束后,被jin哥哥分配第一个任务,他就说了一句话“那你今天测一个feature”吧,当时听完就有一个晕菜的感觉,尼玛feature是啥,尼玛怎么测试。。。</li>
<li>2013年8月20日,已经持续了2个月研究flash VI Automation,每天看代码,却不知道如何下手,既无望也无进展,正在这个关节上,公司宣布弃用flash,开始做html5,心中既难过却又稍微松了一口气。很久之后,我才明白,这是头们的策略,那时的我一心想去robert组,想做automation,经过这么2个月,开始回到现实,很多事情真的没有那么容易,有多大的本事做多大的事,想一口吃个胖子那是不可能的。很久之后,我也渐渐认识到,自己对于环境的熟悉和摸索过程特别慢,那时候有时候很苦闷,却不愿意去问问题,而想要做成的事情需要各方面的努力和协调,远远不是那时候的我可以完成的。同一天,也开始接触ios安全工作方面的工作,开始测试DPC这个feature。</li>
<li>2013年9月2号,似乎是这一天,接下了Mobile SDK的活。哈哈,还记得自己跟p姐和gloria在办公室愤慨激昂,表达着自己对于“挑战”和工作任务的渴望,搞得gloria问我是啥星座,我回答狮子座,她来了一句,果然。从此,在头们眼中,女汉子的角色已经成功定型。</li>
<li>2013年9月还是10月的某一天,开始跟着feng哥学习configuration/certificate server相关的工作,作为一个临时的backup。当然那时候的学习还是比较浅尝辄止的。</li>
<li>2013年12月的某一天,接下usher integration这个feature,开始的时候以为只是一个很简单的东西,而且只是为了demo的使用,后来发现是一个很大的坑,涉及到的东西很多很多,也正是从这个feature开始,对于feature testing有了比较直观的认识和理解。也是在12月份,混入了security committee,参加他们2周一次的会议,当然基本不发言,也有很多东西听不懂。应该也是在这个月,组里搞了一次team event,分组唱歌,运气不错,跟着jin哥哥混了个第一,第一次见识到jin哥哥的舞蹈,可惜因为在认真唱歌,没有好好欣赏,之后也再也没有见到过,一切都成为传说了。</li>
<li>2014年1月下旬的某一天,ctc搬家,之后feng哥就坐我后面,这大概是从这之后,或者是过年之后,正式得到feng哥非常detail的指导,他时常监督,耐心非比寻常,硬是把我log issue丢三落四的习惯,经过应该有10来次的“这个regression flag”没设,那个不是”customer issue”之类的提醒,终于改掉了。一直以来很感激feng哥,很认真地辅导,每次我表示感谢的时候,他都说,他觉得我是一个很值得教的人,他很乐意。我觉得很幸运。</li>
<li>2014年4月,公司调薪,虽然不多,但是我自己觉得对于我工作第一年的表现并不是特别满意,也没有很大的成果,但p姐还有gloria都对我很信任,所以虽然对薪资不满,我已觉得很开心。</li>
<li>2014年6月,得知feng哥下个月离职,虽早有心理准备,但还是觉得措手不及,很多东西都没有学好。走之前,feng哥还不忘给我一些良言,受益颇多。这2个月也学习了不少security的知识,花了不少自己的课外时间学习。回想起来,虽然以后不一定做这个方向,但这些学习对自己只有好处,开阔了视野,也开阔了思维。</li>
<li>2014年8月22日,永远难忘,公司第一波裁员,jingxiong小伙伴不幸在名单之中,特别难受,但那时候已经开始觉得走了也没什么不好,很多时候我们都是一叶障目,不见森林,离开这里,寻找更广阔的天空也许更好。</li>
<li>2014年9月,一批新人入组,有了第一个徒弟,经过苦逼的几个月之后,又开始对工作充满了热情,很认真地教,可惜实在是自己的翅膀还没硬,所以把自己搞得更加苦逼了。同时为了给新人腾位子,我搬到了feng哥曾经坐的window seat,每天可以晒到太阳,也开始喜欢每天跟gloria闲扯,聊聊天。可惜天有不测风云,9月底,这批新人被裁员了。从此有些时光一去不复返了。</li>
<li>2014年10月,jin哥哥也走了,虽然知道像jin哥哥这种牛人,迟早留不住,但是其实他们对于公司很有感情,很多时候也是没有办法,人生需要move on,不同的时期需要不同的平台,这种选择显得非常的顺其自然。</li>
<li>2014年12月,公司重组终于要慢慢落下帷幕,我也趁此机会申请了转SE,虽然说还很有多的不确定,也不知道未来是什么样,但在这个过程中,我无比感谢gloria和p姐对我的信任,努力为我争取机会,我会一直牢记在心。</li>
</ul>
<p>没想到一不小心就写了这么多,也没想到第一份工作会是这样的际遇,虽然看不清未来,但依然感激工作带给自己的成长,至少我对测试行业有了比较直观的理解和认知,我也学到很多很多的知识,还遇到了这么多对我这么好的人,我想这也就够了。</p>
<h3>学习</h3>
<p>今年也花了不少时间在学习上,想努力提高自己。</p>
<ul>
<li>安全相关: ios学习了逆向工程以及一些基础的实践;web入了门,web前端黑客技术揭秘以及白帽子讲web安全都看了一些;粗略地学习了密码学。感觉安全这个行业还是很有前途的,但是实在是很难,而且需要非常浓烈的兴趣,我几次想深入学习,却又止步门外,未来可以怎样,还得看自己。</li>
<li>ios相关:温习了objective-c语言;看了iOS与OSX多线程和内存管理以及bignerd并写下几篇读书笔记;跟了一些博客,比如objc等</li>
<li>其他:粗略地学习了ruby,python,javascript,php等,发现会一门语言之后,对于其他语言只入门实在是用处不大,对于语言的学习最好的场景还是使用和实践,否则很难进步。粗略学习了编译原理。尝试跟了下coursera和网易公开课的课程,却总是半途而废。</li>
<li>博客:基于github搭建了个人博客,10月底到11月写下了不少文章,可惜12月份找了个理由便不再更新。</li>
</ul>
<h3>生活</h3>
<p>奇怪的很,对于生活,似乎都想不起来很多细节了,大概是因为是太过于平淡。</p>
<ul>
<li>买了好多书,可惜坚持看完的没有几本,认真看了的大概只有亲爱的安德烈,最好金龟换酒,你的孤独虽败犹荣。想想好惭愧,好久没有认真看下书了,这是为什么呢?是因为下面这条。</li>
<li>电视剧,看了好多电视剧,总是一看就停不下来,大概是因为看电视剧实在是不费脑,所以花在这上面的时间着实是有点多了。</li>
<li>由于最近这一个月老妈来了,每天的生活变得异常简单,吃饭上班散步锻炼,早早休息,以至于我都有些忘记之前的日子是什么模样了。不过也体验到,这就是最最真实,最最平凡的生活了吧。人生的真谛大概也就是这样了,追寻梦想,陪伴家人。</li>
</ul>
<h3>展望与新年计划</h3>
<p>今年一年总的来说,有些小混乱,知识的学习不太有体系,很多东西没有坚持。但也有值得肯定的地方,比如至少有一小半的时间在坚持学习,比如开始写博客,比如学会做选择。</p>
<p>新的一年,姑且给自己定几个愿望和目标吧。</p>
<ul>
<li>坚持写博客,不要求多,一周至少一篇吧</li>
<li>努力提升技术,希望能看到更广阔的天空,不管是做SE还是QE,学习一定要坚持</li>
<li>在coursera/网易公开课至少完整地跟一门课程,不论是什么课程都可以</li>
<li>看10本书,开阔视野,争取也能写几篇书评</li>
<li>阳光一点,心态开阔一点,这一点很虚,但最重要</li>
</ul>
<p>最后一句话自勉,坚持努力,相信生命中会有美好的事情发生。明年今日再来重读这篇文章。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[谈谈iOS Security]]></title>
<link href="http://straybirdzls.github.io/blog/2014/11/30/security/"/>
<updated>2014-11-30T21:33:59+08:00</updated>
<id>http://straybirdzls.github.io/blog/2014/11/30/security</id>
<content type="html"><![CDATA[<p>近一年多跟iOS的交互中有一半都是与security的,其实现在关于iOS security的讨论也有非常多了,这里只是对于自己的学习和工作做一个小小的总结。</p>
<!--more-->
<h4>怎样测试一个app的安全?</h4>
<p>与安全相关的面试中,这是一个绝对的热点,根据我自己的浅见以及学习,我觉得需要考虑的如下:</p>
<ol>
<li><p>数据存储</p>
<p> 数据存储表面看起来很简单,但实际上却是移动app中最容易出现的安全问题。在数据存储中,我们有很多需要注意的地方:1.第一步一定是play with app,这个的目的一方面是熟悉app的功能,另一方面是尽可能多的产生一些本地文件 2.本地数据的存储主要包含在2处,一个是app的sandbox,另一个就是keychain 3.app的sandbox中文件很多,这里需要注意的就是关键敏感信息的处理,一定是需要加密的,说到加密,加密算法的使用也非常重要,比如hash的话至少要加盐等,对于sandbox中的文件,我们需要认真对待,很多敏感信息泄漏都出在这里,比如用户名/密码,server地址等等 4.keychain在越狱的设备中不安全,也这是众所周知的,但很多app可能依然就将明文存在keychain中</p></li>
<li><p>网络通信</p>
<p> 现在的移动app都会与服务器进行通信,网络通信中的中间人攻击很常见,http受到攻击太容易了,https的话要看有没有启用certificate pinning,没有的话,攻击起来也不困难。在与服务器的交互之中也涉及到一些web安全的东西,也要考虑暴露服务器的脆弱性的问题。有些app的服务器将数据传回客户端时候就完全信任客户端,这也是非常不安全的。</p></li>
<li><p>动态攻击</p>
<p> 动态攻击涉及到的就是逆向工程了,逆向工程威力很强大,比如代码泄漏/bypass一些关键的逻辑等,所以要看app有没有做binary的保护,没有的话,可以做的事情那就多了。动态攻击方面主要是检查有没有暴露在外很容易攻击又很关键的接口,脆弱的逻辑等等。</p></li>
</ol>
<h4>需要学习的知识点</h4>
<p>做安全一定是要懂开发的,对于ios的一些系统知识也需要了然于心,比如mach-o格式等,还需要掌握很多工具,比如class-dump/theos/gdb/lldb等等.</p>
<p>今晚由于时间紧张,暂时就写这么多了,回头有机会再细化补全。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[iOS学习笔记2]]></title>
<link href="http://straybirdzls.github.io/blog/2014/11/26/viewcontroller/"/>
<updated>2014-11-26T22:12:09+08:00</updated>
<id>http://straybirdzls.github.io/blog/2014/11/26/viewcontroller</id>
<content type="html"><![CDATA[<p>这一篇接上篇,依然是iOS Programming: The Big Nerd Ranch Guides这本书的学习笔记,这本书对于各种点讲的还比较清楚,这一篇主要集中在view controller相关的点上。</p>
<!--more-->
<h4>View Controller之间的关系</h4>
<p>刚开始的时候,容易被View Controller之间的关系搞迷糊,其实归根到底关系就2种,family关系和presented/presenting关系。</p>
<p>family关系,显而易见,就是包含关系了,一个view controller包含几个子view controller,可以通过UIViewController的viewControllers来获取。子view controller可以通过parentViewController/navigationController/tabBarController/splitViewController来获取父controller,当然后3个都是会顺着view controller的关系往上查找相应的view controller类型,若没有,则返回nil。</p>
<p>presented/presenting关系,描述的是一种模态controller,presented的controller将会之于当前view的top之上,可以通过presentedViewController/presentingViewController来访问。值得注意的是1).family中有一个view controlly拥有presentedViewController,则其他的也跟着拥有; 2).默认的presentingViewController会去controller family里寻找最父级的controller,如果不想拥有这种行为,需要将view controller的definesPresentationContext属性设为YES,并将modalPresentationStyle设置为UIModalPresentationCurrentContext。</p>
<h4>UITableViewController</h4>
<p>UITableViewController是实际中非常常用的view conroller,其自带了一个tableView,然后还拥有delegate和datasource,datasource主要是用来管理数据源,其只用来数据源的获取和刷新,真正跟tableview交互的是delegate。UITableViewController自带的API非常丰富,从我的学习中,有需求的时候就多看看API的说明,总能找到一款满足需求的API。</p>
<p>本来还想再多写一点,结果发现很多东西不是三言两语可以说得清楚,只需要自己动手跟着书中的例子走一遍,然后再实践几次,慢慢地熟悉了,就都了然于心了。</p>
<h3>参考文献</h3>
<p>书籍: iOS Programming: The Big Nerd Ranch Guides</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[iOS学习笔记1]]></title>
<link href="http://straybirdzls.github.io/blog/2014/11/21/views/"/>
<updated>2014-11-21T20:40:43+08:00</updated>
<id>http://straybirdzls.github.io/blog/2014/11/21/views</id>
<content type="html"><![CDATA[<p>接触iOS这个平台也有1年多的时间了,中途有看过一些书,也看过一些博客,但终究觉得是纸上得来终觉浅。最近也好好思考了一下,对于iOS的学习一直都是随性的,想到啥了就学啥,导致的结果就是有些部分因为比较感兴趣,学的比较深入,有些部分却是一个完完全全的初学者,所以当自己想去写点什么的时候,总是有点力不从心。总结了一下,现在对于objetctive-c的语法,以及ios的内存管理,多线程等方面至少是应该跨过了初学者的层次,但是对于view,controller还有Apple提供的api等知道的甚少。正好最近有同事推荐了iOS Programming: The Big Nerd Ranch Guides,网上看了一下,觉得挺不错的,对于现阶段的我,正好可以查缺补漏,同时练手和巩固已有知识。这个学习笔记系列也就是我学习过程中的一些记录。</p>
<!--more-->
<h3>id和instancetype</h3>
<p><code>instanceytype</code>只能够作为返回值类型,并且会返回当前的class类型,相对于id而言,其可以让编译器帮我们做更多的事情。之前我也想过,为什么初始化中一定要返回<code>id</code>或者<code>instancetype</code>,不能直接返回类类型呢?在书中也找到了答案,其实很简单,如果类被子类化了怎么办?子类覆盖?我们知道objeitive-c中是不能有selector名字一致但是返回类型不一致的方法的。</p>
<h3>view/controller相关</h3>
<h5>Point和Pixel</h5>
<p>涉及到viewer层面,就不得不提Point和Pixel了,Point的大小参数是保持一致的,根据屏幕分辨率的不同,其对应的Pixel的数量会发生改变。在非Retina屏中,1个Point就是Pixel,但在Retina中,一个Point变为了2*2Pixel。所以对于图片而言,苹果提高了非常便捷的方式,就是用2份图片,在Retina中使用的在名字后加上@2x就可以了。</p>
<h5>lazy loading</h5>
<p>对于view而言,没有显示在屏幕之上前,viewcontroller是没有必要去loading的,同时也考虑到移动端的内存,我们应该尽量做到这样。所以我们一定要注意,没有必要的时候不要在这之前调用self.view,尤其不要在init中调用,这样会造成view的提前加载。</p>
<h5>xib命名</h5>
<p>xib的命名最好与viewcontroller的名字保持一致,这是为什么呢?因为<code>initWithNibName</code>调用时,如果发现nib参数为空,会检测与viewcontroller同名的nib文件,也就是说名字保持一致后,就可以直接使用init初始化了,这样是不是方便很多?</p>
<h5>File’s owner</h5>
<p>对于xib而言,设置file’s owner非常重要,这是为什么呢,如果不设置,当viewcontroller加载nib时,元素都准备好了,却会发现自己的view指向nil,将xib的file’s owner设置为对应的view controller,就可以将view的outlet设置为file’s owner了,这样,加载的时候,view controller成为file’s owner,就能找到对应的view了。</p>
<h5>outlet的背后</h5>
<p>在xib上设置outlet只需要简单的拖动,那实际上view上的元素outlet到底是怎么跟viewcontroller中的property连接起来的呢?这背后其作用的就是<code>kvc(key-value coding)</code>了,首先会寻找setter/getter,然后是成员变量(var和_var),所以当设置好outlet之后,如果将对应的property改名,就会寻找不到,也是这个原因。</p>
<h5>Core Graphics</h5>
<p>Core Graphics是用纯c语言实现的2D作图引擎,其中有一些以Ref结尾的类型需要注意,他们其实是指针对象的,用Ref又作了一层封装以与其他的Core框架对象保持一致(Core Foundation中也有很多这样的),尽管这些对象是存在堆上的,但是ARC不帮忙管理内存,需要我们自己管理。大部分时候我们我们都会选用跟高层面的实现UIBezierPath,但是阴影和渐变只能用Core Foundation实现。</p>
<p>这一篇记录的也比较杂,主要是根据学习的顺序吧,记录的目的也就是帮助自己巩固知新。</p>
<h3>参考文献</h3>
<p>书籍: iOS Programming: The Big Nerd Ranch Guides</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Python学习笔记]]></title>
<link href="http://straybirdzls.github.io/blog/2014/11/18/pythonstart/"/>
<updated>2014-11-18T22:50:01+08:00</updated>
<id>http://straybirdzls.github.io/blog/2014/11/18/pythonstart</id>
<content type="html"><![CDATA[<p>最近开始学习coursera上的<a href="https://class.coursera.org/pythonlearn-003">python教程</a>,这门课程相当简单,是面向刚接触编程的,对于已经有个编程基础的,可以权当花少量的时间,过一下语法。我学这门课程花的时间也不多,发现python语法中的确有一些不一样的地方,这里记录一下。</p>
<h4>缩排</h4>
<p>python中识别代码快是用缩进的,值得注意的是要保持缩进的格式一致,一定记得不要将tab和空格混用,否则容易带来很难检查的缩进错误,建议编写python代码时,将编辑器做一些设定,让tab自动成为空格。</p>
<!--more-->
<h4>值得注意的语法</h4>
<p>python中还是有不少语法跟之前接触过的有不少的差别,这里列一些我觉得值得注意的</p>
<ol>
<li>语句末尾不需要;作为结束符,有的话会报错</li>
<li>很多常见的语句都需要用:结尾 比如<code>if/elif/else/if not,try/except,def,while,for...in</code>,且这些语句的内容都不需要用()包起来,我一开始总是习惯性地打括号。</li>
<li><code>for...in:</code>非常好用,不仅仅对于数组,对于字符串也可以直接使用,遍历起来非常方便。对于文件也非常好用,利用<code>open()</code>打开文件之后,就可以直接用其来遍历文件的内容,如果用<code>read</code>,则是将文件内容读入到字符串中。</li>
<li>字符串自带的处理函数很丰富,使用<code>dir(str)</code>即可查看内建的字符串函数,很常用的有<code>lstrip()/strip()/rstrip()</code>,<code>split()</code>,<code>startswith()/endswith()</code>等等。</li>
<li>很好用的<code>in</code>,这里的<code>in</code>不是<code>for...in</code>里面的那个,其可以直接用来判断字符串中是否包含子串,数组中是否包含某元素等,当然对应的还有<code>not in</code>。</li>
<li><code>list</code>很好用,遍历等的方式也都跟字符串保持一致,但字符串本身赋值后就不能修改,修改会报错,其是”不可变的”,而<code>list</code>则可以,其是”可变的”。</li>
<li>字符串使用<code>split()</code>可以生成<code>list</code>,<code>split()</code>也可以带参数,指定分割字符串所用的符号,非常好用。</li>
<li><code>'''</code>可以用作注释用途,但是它不等价于注释。其中的内容可以通过help打印出来。</li>
<li><code>dictionary</code>和<code>list</code>一个很重要的区别是后者可以保持元素的顺序,而前者不能。对于<code>dictionary</code>而言,<code>for...in:</code>遍历的<code>iterator</code>是<code>key</code>,使用<code>list(dic)</code>,即可转变成<code>list</code>, 当然其值为<code>key</code>,而<code>keys</code> <code>values</code> <code>items</code>也可以将其转变为对应的<code>list</code>。<code>get</code>非常有用,其有2个参数,其中第一个参数为<code>key</code>,第二个参数为默认值,也就是如果找到了<code>key</code>,则返回对应的<code>values</code>,如果没有,则返回默认值。</li>
<li><code>tuple</code>和<code>list</code>的一个区别就是<code>list</code>是可变的,而<code>tuple</code>是可变的。<code>tuple</code>由<code>()</code>包围,<code>list</code>由<code>[]</code>包围,而 <code>dictionary</code>由<code>{}</code>包围。<code>tuple</code>有一个很重要的特性,其可放到表达式的左边同时给多个变量赋值。<code>tuple</code>可以比较大小,因此可以对包含<code>tuple</code>的<code>list</code>进行<code>sort</code>。对<code>dictionary</code>取<code>items</code>时就是将其变成包含<code>tuple</code>的<code>list</code>,因为可以同时使用<code>keys</code> 和<code>values</code>进行遍历。</li>
<li>python的re模块提供了对正则表达式的支持,使用时只需要<code>import re</code>就可以啦,正则表达式并不是python的一部分,所以这里就不详细介绍了。</li>
</ol>
<h4>is和==</h4>
<p>python中判断是否相等,有<code>is</code>和<code>==</code>,其中<code>is</code>是判断是否相等,而==则用同时判断值和类型,比如1==1.0返回True,而1 is 1.1返回False。提到<code>is</code>,就不得不提<code>None</code>,<code>None</code>表示参数未定义,一般情况下判断是否为<code>None</code>,都推荐用<code>is</code>。</p>
<p>这门公开课也算是跟完了,但是的确是比较基础入门的,想要学习python,还需要更多其他的学习和练习。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[谈谈Foundation]]></title>
<link href="http://straybirdzls.github.io/blog/2014/11/16/xianche/"/>
<updated>2014-11-16T20:20:49+08:00</updated>
<id>http://straybirdzls.github.io/blog/2014/11/16/xianche</id>
<content type="html"><![CDATA[<p>Founcation Kit是Cocoa中非常重要的一员,其提供了很多方便使用的数据对象类型。Foundation是基于Core Foundation实现的,后者是用纯C语言写的,它们之间进行转变也非常方便。这一篇我主要是记录一些在学习Foundation中觉得应该特别注意的几个点。</p>
<h4>类簇</h4>
<p>在Foundation中类簇非常常见,比如<code>NSArray,NSNumber</code>等。类簇的本质其实是抽象工厂模式,使用这个的好处就是用户在使用这些<code>NSArray,NSNumber</code>时,不用去考虑具体实例化的对象是属于什么类。值得注意一点的是,千万不要创建类簇的子类,处理不好的话会是灾难。关于类簇,更多的信息可见参考文献2,该文阐述的非常清晰,并给出了具体的使用场景。</p>
<!--more-->
<h4>Copy</h4>
<p>关于拷贝,objective-c中提供了<code>copy</code>关键字,容易混淆的还有<code>retain</code>关键字。一般认为<code>retain</code>为指针拷贝,<code>copy</code>为内容拷贝,内容拷贝中又包含了深拷贝和浅拷贝。对于不可变的对象而言,copy做的事情与retain保持了一致:引用计数加1;对于可变的对象而言,copy是浅拷贝。测试代码如下:</p>
<pre><code>NSMutableArray *mutableArray = [NSMutableArray arrayWithObject:@"test"];
NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithObject:@"test1" forKey:@"1"];
[mutableArray addObject:mutableDictionary];
NSArray *array = [mutableArray copy];
[mutableDictionary setObject:@"test2" forKey:@"2"];
[mutableArray addObject:@"test3"];
NSLog(@"array is %@",array);
NSLog(@"mutableArray is %@",mutableArray);
</code></pre>
<p>输出结果如下,可以看到array中mutableDictionary依然会跟着改变。</p>
<pre><code>array is (test,{1 = test1;2 = test2;})
mutableArray is (test,{1 = test1;2 = test2;},test3)
</code></pre>
<h4>什么时候不应该使用属性?</h4>
<p>这一点属于摘录,在参考文献1中提到</p>
<blockquote><p>在初始化方法或者是 dealloc 中最好不要使用属性,因为你无法确定 self 到底是不是确实调用的是你想要的实例</p></blockquote>
<p>在<a href="%E6%AD%A4%E6%96%87">此文</a>中,我也看到类似的论述,虽然也许在<code>init</code>或者<code>dealloc</code>使用属性大部分时候不会带来问题,但还是应该小心为妙。</p>
<p>在参考文献1中,关于Foundation,都是一些非常好的文章,我这里只记录了我暂时看到的几点,只是一点点皮毛,推荐有兴趣的人看看那些文章。</p>
<h3>参考文献</h3>
<p><a href="http://objccn.io/issue-7/">objc中国:#7 Foundation</a><br/>
<a href="http://limboy.me/ios/2014/01/04/class-cluster.html">类簇来iOS开发中的应用</a></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[读书笔记(3) iOS与OSX多线程和内存管理]]></title>
<link href="http://straybirdzls.github.io/blog/2014/11/11/memeorybook3/"/>
<updated>2014-11-11T20:30:54+08:00</updated>
<id>http://straybirdzls.github.io/blog/2014/11/11/memeorybook3</id>
<content type="html"><![CDATA[<p>今天是<iOS与OSX多线程和内存管理>读书笔记的最后一篇了,主题是多线程。书中主要是讲GCD,并没有讲NSOperation的东西,我这一篇一方面简要地对GCD记录一些知识点,也谈一点点NSOperation方面的东西。对于NSOperation方面的知识,我看了很多人推荐的<a href="http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues">教程</a>,觉得写得非常好,推荐想学习的人看一看。</p>
<h4>慎用@sync</h4>
<p>从字面意思<code>@async</code>是异步执行,那<code>@sync</code>就是同步执行了。使用<code>@sync</code>时一定要万分小心,比如主线程,则会直接造成阻塞,死锁。因为任务执行完之后才会返回,但任务又必须等待其之前的任务完成才能执行。</p>
<!--more-->
<h4>UI刷新</h4>
<p>移动端非常注重用户体验,所以UI刷新一定要放在主线程。若使用GCD,可以用<code>dispatch_get_main_queue()</code>来获取主线程,若使用NSOperation,可以用<code>[NSOperationQueue mainQueue]</code>来获取,当然也可以通过delegate使用<code>performSelectorOnMainThread</code>来实现。</p>
<h4>一些好用的关键字</h4>
<p>在GCD中,有很多很好用的功能,比如<code>dispatch_once</code>可以保证代码只被调用一次;<code>dispatch_group_async</code>可以定义一组任务,当一组任务全部完成时,会通过<code>dispatch_group_notify</code>来给通知;<code>dispatch_barrier_async</code>用于等待其他任务的完成,并完成任务之后,才能启动之后的任务,对于数据库访问以及文件的读写都非常有用;<code>dispatch_apply</code>是跟<code>@sync</code>和<code>group</code>都有关系的,它可以定义一组任务,并等待其完成;<code>dispatch_semaphore</code>提供类似于<code>dispatch_barrier_async</code>的功能,但是可以保证更小的粒度,它是通过信号量的方式来工作的。</p>
<h4>NSOperationQueue和GCD</h4>
<p>自GCD出来后,NSOperationQueue就是用GCD来实现了。通过对上面推荐的教程的学习,NSOperation对于代码管理是非常方便的,而且可以cancel,对于依赖的管理也非常方便。根据苹果使用high level实现的惯例,一般情况下都是推荐使用NSOperation。当然GCD很轻量级,使用起来非常方便,所以根据具体的使用场景,也有很多需要的时候。</p>
<p>其实书中还讲了很多其他方面的内容,GCD确实很强大,有了它,我们不用自己管理线程,因为这方面我还处于学习阶段,所以暂时还没能有一些比较深刻的见解,有兴趣的可以看objc的这个<a href="http://objcio.cn/issue-2/">专题</a>,讲得非常精彩。截止到现在,这本书<iOS与OSX多线程和内存管理>我也算是粗略地过了一遍,但实践出真知,我现在还处于学习阶段,接下来要多多练习,方能将这些全部变成自己的知识。</p>
]]></content>
</entry>
</feed>