@@ -411,114 +411,19 @@ self.mutableArray = array;
411411```
412412
413413
414- 至于*** 如何重写带 copy 关键字的 setter*** 这个问题,
415-
416-
417- 如果抛开本例来回答的话,如下:
418-
419-
420-
421- ``` Objective-C
422- - (void )setName:(NSString *)name {
423- //[_name release];
424- _name = [name copy];
425- }
426- ```
427-
428- 不过也有争议,有人说“苹果如果像下面这样干,是不是效率会高一些?”
429-
414+ *** 重写带 copy 关键字的 setter*** :
430415
431416 ``` Objective-C
432417- (void )setName:(NSString *)name {
433418 if (_name != name) {
434- //[_name release];//MRC
419+ #if __has_feature(objc_arc)
420+ [_name release];
421+ #endif
435422 _name = [name copy];
436423 }
437424}
438425 ```
439426
440-
441-
442- 这样真得高效吗?不见得!这种写法“看上去很美、很合理”,但在实际开发中,它更像下图里的做法:
443-
444- ![ enter image description here] ( http://i.imgur.com/UwV9oSn.jpeg )
445-
446- 克强总理这样评价你的代码风格:
447-
448- ![ enter image description here] ( http://i.imgur.com/N77Lkic.png )
449-
450- 我和总理的意见基本一致:
451-
452-
453- > 老百姓 copy 一下,咋就这么难?
454-
455-
456-
457-
458- 你可能会说:
459-
460-
461- 之所以在这里做` if判断 ` 这个操作:是因为一个 if 可能避免一个耗时的copy,还是很划算的。
462- (在刚刚讲的:《如何让自己的类用 copy 修饰符?》里的那种复杂的copy,我们可以称之为 “耗时的copy”,但是对 NSString 的 copy 还称不上。)
463-
464-
465- 但是你有没有考虑过代价:
466-
467-
468- > 你每次调用 ` setX: ` 都会做 if 判断,这会让 ` setX: ` 变慢,如果你在 ` setX: ` 写了一串复杂的 ` if+elseif+elseif+... ` 判断,将会更慢。
469-
470- 要回答“哪个效率会高一些?”这个问题,不能脱离实际开发,就算 copy 操作十分耗时,if 判断也不见得一定会更快,除非你把一个“ @property 他当前的值 ”赋给了他自己,代码看起来就像:
471-
472- ``` Objective-C
473- [a setX: x1] ;
474- [ a setX: x1 ] ; //你确定你要这么干?与其在setter中判断,为什么不把代码写好?
475- ```
476-
477- 或者
478-
479-
480- ```Objective-C
481- [a setX:[a x]]; //队友咆哮道:你在干嘛?!!
482- ```
483-
484- > 不要在 setter 里进行像 ` if(_obj != newObj) ` 这样的判断。(该观点参考链接:[ *** How To Write Cocoa Object Setters: Principle 3: Only Optimize After You Measure*** ] ( http://vgable.com/blog/tag/autorelease/ )
485- )
486-
487-
488- 什么情况会在 copy setter 里做 if 判断?
489- 例如,车速可能就有最高速的限制,车速也不可能出现负值,如果车子的最高速为300,则 setter 的方法就要改写成这样:
490-
491-
492- ``` Objective-C
493- -(void )setSpeed:(int )_speed{
494- if(_speed < 0) speed = 0;
495- if(_speed > 300) speed = 300;
496- _speed = speed;
497- }
498- ```
499-
500-
501-
502- 回到这个题目,如果单单就上文的代码而言,我们不需要也不能重写 name 的 setter :由于是 name 是只读属性,所以编译器不会为其创建对应的“设置方法”,用初始化方法设置好属性值之后,就不能再改变了。( 在本例中,之所以还要声明属性的“内存管理语义”--copy,是因为:如果不写 copy,该类的调用者就不知道初始化方法里会拷贝这些属性,他们有可能会在调用初始化方法之前自行拷贝属性值。这种操作多余而低效)。
503-
504- 那如何确保 name 被 copy?在初始化方法(initializer)中做:
505-
506- ``` Objective-C
507- - (instancetype )initWithName:(NSString *)name
508- age:(NSUInteger )age
509- sex:(CYLSex)sex {
510- if(self = [super init]) {
511- _name = [name copy];
512- _age = age;
513- _sex = sex;
514- _friends = [[NSMutableSet alloc] init];
515- }
516- return self;
517- }
518-
519- ```
520-
521-
522427
523428###6 . @property 的本质是什么?ivar、getter、setter 是如何生成并添加到这个类中的
524429
0 commit comments