From e71a4b1dd7038d162921dd51e9ce70d9bcf000b1 Mon Sep 17 00:00:00 2001 From: Ruqi Date: Thu, 29 Oct 2015 18:17:40 +0800 Subject: [PATCH 01/14] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=85=B3=E4=BA=8E?= =?UTF-8?q?=E6=B7=B1=E6=8B=B7=E8=B4=9D=E7=9B=B8=E5=85=B3=E7=9A=84=E6=8F=8F?= =?UTF-8?q?=E8=BF=B0=E5=92=8C=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 文中的 `- deepCopy` 方法并不能实现深拷贝。 `CYLUser` 的 `- copyWithZone` 方法里,`_friends` 成员的的赋值使用的 `- mutableCopy` 是浅拷贝,只是创建了`NSMutableSet` 对象;导致 `- deepCopy`方法中, _friends 的每一个对象的 _friends 列表并未创建实例。 为了测试 `NSArray`, `NSSet` 容器类初始化行为,我写了测试代码, ``` NSMutableArray *objects = [NSMutableArray array]; [objects insertObject:[NSDate date] atIndex:0]; if ([objects count] > 0) { NSArray *arr = [[NSArray alloc] initWithArray: objects]; for (int i=0; i - -@property (nonatomic, readonly, copy) NSString *name; -@property (nonatomic, readonly, assign) NSUInteger age; -@property (nonatomic, readonly, assign) CYLSex sex; - -- (instancetype)initWithName:(NSString *)name age:(NSUInteger)age sex:(CYLSex)sex; -+ (instancetype)userWithName:(NSString *)name age:(NSUInteger)age sex:(CYLSex)sex; -- (void)addFriend:(CYLUser *)user; -- (void)removeFriend:(CYLUser *)user; - -@end -``` - -// .m文件 - - - - ```Objective-C -// .m文件 -// http://weibo.com/luohanchenyilong/ -// https://github.com/ChenYilong -// - -@implementation CYLUser { - NSMutableSet *_friends; -} - -- (void)setName:(NSString *)name { - _name = [name copy]; -} - -- (instancetype)initWithName:(NSString *)name - age:(NSUInteger)age - sex:(CYLSex)sex { - if(self = [super init]) { - _name = [name copy]; - _age = age; - _sex = sex; - _friends = [[NSMutableSet alloc] init]; - } - return self; -} - -- (void)addFriend:(CYLUser *)user { - [_friends addObject:user]; -} - -- (void)removeFriend:(CYLUser *)user { - [_friends removeObject:person]; -} - -- (id)copyWithZone:(NSZone *)zone { - CYLUser *copy = [[[self class] allocWithZone:zone] - initWithName:_name - age:_age - sex:_sex]; - copy->_friends = [_friends mutableCopy]; - return copy; -} - -- (id)deepCopy { - CYLUser *copy = [[[self class] allocWithZone:zone] - initWithName:_name - age:_age - sex:_sex]; - copy->_friends = [[NSMutableSet alloc] initWithSet:_friends - copyItems:YES]; - return copy; -} - -@end - - ``` - -以上做法能满足基本的需求,但是也有缺陷: - -> 如果你所写的对象需要深拷贝,那么可考虑新增一个专门执行深拷贝的方法。 - -【注:深浅拷贝的概念,在下文中有介绍,详见下文的:***用@property声明的 NSString(或NSArray,NSDictionary)经常使用 copy 关键字,为什么?如果改用 strong 关键字,可能造成什么问题?***】 - -在例子中,存放朋友对象的 set 是用 “copyWithZone:” 方法来拷贝的,这种浅拷贝方式不会逐个复制 set 中的元素。若需要深拷贝的话,则可像下面这样,编写一个专供深拷贝所用的方法: - - - ```Objective-C -- (id)deepCopy { - CYLUser *copy = [[[self class] allocWithZone:zone] - initWithName:_name - age:_age - sex:_sex]; - copy->_friends = [[NSMutableSet alloc] initWithSet:_friends - copyItems:YES]; - return copy; -} - - ``` 至于***如何重写带 copy 关键字的 setter***这个问题, From 4127d6b11a22580e3d884d4f5f104df5170a61f7 Mon Sep 17 00:00:00 2001 From: Ruqi Date: Thu, 29 Oct 2015 18:51:27 +0800 Subject: [PATCH 02/14] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20*=E9=87=8D=E5=86=99?= =?UTF-8?q?=E5=B8=A6=20copy=20=E5=85=B3=E9=94=AE=E5=AD=97=E7=9A=84=20sette?= =?UTF-8?q?r*=20=E7=9A=84=E7=AD=94=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 首先,if 的确比对象 copy 要快。 另外,判断对象是否相同是为了保证代码执行的正确性。在非 ARC 环境下,如果穿入对象 retain count 为 1,不做判断的话,release 之后对象内存释放,下一步 copy 也会出错。 --- ...10\357\274\210\344\270\212\357\274\211.md" | 103 +----------------- 1 file changed, 4 insertions(+), 99 deletions(-) diff --git "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" index 03f5778..cd7e6a6 100644 --- "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" +++ "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" @@ -411,114 +411,19 @@ self.mutableArray = array; ``` -至于***如何重写带 copy 关键字的 setter***这个问题, - - -如果抛开本例来回答的话,如下: - - - -```Objective-C -- (void)setName:(NSString *)name { - //[_name release]; - _name = [name copy]; -} -``` - -不过也有争议,有人说“苹果如果像下面这样干,是不是效率会高一些?” - +***重写带 copy 关键字的 setter***: ```Objective-C - (void)setName:(NSString *)name { if (_name != name) { - //[_name release];//MRC +#if __has_feature(objc_arc) + [_name release]; +#endif _name = [name copy]; } } ``` - - -这样真得高效吗?不见得!这种写法“看上去很美、很合理”,但在实际开发中,它更像下图里的做法: - -![enter image description here](http://i.imgur.com/UwV9oSn.jpeg) - -克强总理这样评价你的代码风格: - -![enter image description here](http://i.imgur.com/N77Lkic.png) - -我和总理的意见基本一致: - - -> 老百姓 copy 一下,咋就这么难? - - - - -你可能会说: - - -之所以在这里做`if判断` 这个操作:是因为一个 if 可能避免一个耗时的copy,还是很划算的。 -(在刚刚讲的:《如何让自己的类用 copy 修饰符?》里的那种复杂的copy,我们可以称之为 “耗时的copy”,但是对 NSString 的 copy 还称不上。) - - -但是你有没有考虑过代价: - - -> 你每次调用 `setX:` 都会做 if 判断,这会让 `setX:` 变慢,如果你在 `setX:`写了一串复杂的 `if+elseif+elseif+...` 判断,将会更慢。 - -要回答“哪个效率会高一些?”这个问题,不能脱离实际开发,就算 copy 操作十分耗时,if 判断也不见得一定会更快,除非你把一个“ @property他当前的值 ”赋给了他自己,代码看起来就像: - -```Objective-C -[a setX:x1]; -[a setX:x1]; //你确定你要这么干?与其在setter中判断,为什么不把代码写好? -``` - -或者 - - -```Objective-C -[a setX:[a x]]; //队友咆哮道:你在干嘛?!! -``` - -> 不要在 setter 里进行像 `if(_obj != newObj)` 这样的判断。(该观点参考链接:[ ***How To Write Cocoa Object Setters: Principle 3: Only Optimize After You Measure*** ](http://vgable.com/blog/tag/autorelease/) -) - - -什么情况会在 copy setter 里做 if 判断? -例如,车速可能就有最高速的限制,车速也不可能出现负值,如果车子的最高速为300,则 setter 的方法就要改写成这样: - - -```Objective-C --(void)setSpeed:(int)_speed{ - if(_speed < 0) speed = 0; - if(_speed > 300) speed = 300; - _speed = speed; -} -``` - - - -回到这个题目,如果单单就上文的代码而言,我们不需要也不能重写 name 的 setter :由于是 name 是只读属性,所以编译器不会为其创建对应的“设置方法”,用初始化方法设置好属性值之后,就不能再改变了。( 在本例中,之所以还要声明属性的“内存管理语义”--copy,是因为:如果不写 copy,该类的调用者就不知道初始化方法里会拷贝这些属性,他们有可能会在调用初始化方法之前自行拷贝属性值。这种操作多余而低效)。 - -那如何确保 name 被 copy?在初始化方法(initializer)中做: - - ```Objective-C - - (instancetype)initWithName:(NSString *)name - age:(NSUInteger)age - sex:(CYLSex)sex { - if(self = [super init]) { - _name = [name copy]; - _age = age; - _sex = sex; - _friends = [[NSMutableSet alloc] init]; - } - return self; - } - - ``` - - ###6. @property 的本质是什么?ivar、getter、setter 是如何生成并添加到这个类中的 From ad9197a58d68258f89c495ec89804c328bf60bd9 Mon Sep 17 00:00:00 2001 From: Ruqi Date: Fri, 30 Oct 2015 10:55:19 +0800 Subject: [PATCH 03/14] Fix links --- README.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 9d450fc..b1e458c 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,11 @@ -# iOSInterviewQuestions(面试题学习交流群:498865024) -iOS面试题集锦(附答案) +# iOSInterviewQuestions +iOS面试题及答案 -第一篇 : [《招聘一个靠谱的 iOS》—参考答案(上)](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md) - -第二篇 : [《招聘一个靠谱的 iOS》—参考答案(下)](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md) - +第一篇 : [《招聘一个靠谱的 iOS》—参考答案(上)](https://github.com/liruqi/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md) +第二篇 : [《招聘一个靠谱的 iOS》—参考答案(下)](https://github.com/liruqi/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md) 面试题来源是[微博@我就叫Sunny怎么了](http://weibo.com/u/1364395395)的这篇博文:[《招聘一个靠谱的 iOS》](http://blog.sunnyxx.com/2015/07/04/ios-interview/),其中共55题,除第一题为纠错题外,其他54道均为简答题。 -博文中给出了高质量的面试题,但是未给出答案,我尝试着总结了下答案,分两篇发:这是[上篇](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md) ,这是[下篇](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md) 。请持续关注[微博@iOS程序犭袁](http://weibo.com/luohanchenyilong/)。 - -![enter image description here](http://www.resumetarget.com/blog/wp-content/uploads/2013/06/bad-interview.jpg) \ No newline at end of file +![enter image description here](http://www.resumetarget.com/blog/wp-content/uploads/2013/06/bad-interview.jpg) From 9483218810f2aadb8c167f923f57d816c530af31 Mon Sep 17 00:00:00 2001 From: liruqi Date: Fri, 30 Oct 2015 15:41:20 +0800 Subject: [PATCH 04/14] Clean up --- ...10\357\274\210\344\270\212\357\274\211.md" | 24 +++---------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" index cd7e6a6..ef3da7f 100644 --- "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" +++ "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" @@ -1,13 +1,5 @@ [《招聘一个靠谱的 iOS》](http://blog.sunnyxx.com/2015/07/04/ios-interview/)—参考答案(上) - -说明:面试题来源是[微博@我就叫Sunny怎么了](http://weibo.com/u/1364395395)的这篇博文:[《招聘一个靠谱的 iOS》](http://blog.sunnyxx.com/2015/07/04/ios-interview/),其中共55题,除第一题为纠错题外,其他54道均为简答题。 - - -出题者简介: 孙源(sunnyxx),目前就职于百度,负责百度知道 iOS 客户端的开发工作,对技术喜欢刨根问底和总结最佳实践,热爱分享和开源,维护一个叫 forkingdog 的开源小组。 - -答案为[微博@iOS程序犭袁](http://weibo.com/luohanchenyilong/)整理,未经出题者校对,如有纰漏,请向[微博@iOS程序犭袁](http://weibo.com/luohanchenyilong/)指正。 - ---------- #索引 @@ -477,8 +469,8 @@ self.mutableArray = array; > “自动合成”( autosynthesis) -完成属性定义后,编译器会自动编写访问这些属性所需的方法,此过程叫做“自动合成”(autosynthesis)。需要强调的是,这个过程由编译 -器在编译期执行,所以编辑器里看不到这些“合成方法”(synthesized method)的源代码。除了生成方法代码 getter、setter 之外,编译器还要自动向类中添加适当类型的实例变量,并且在属性名前面加下划线,以此作为实例变量的名字。在前例中,会生成两个实例变量,其名称分别为 +完成属性定义后,编译器会自动编写访问这些属性所需的方法。这个过程由编译 +器在编译期执行,所以Xcode里看不到这些“合成方法”(synthesized method)的源代码。除了生成方法代码 getter、setter 之外,编译器还要自动向类中添加适当类型的实例变量,并且在属性名前面加下划线,以此作为实例变量的名字。在前例中,会生成两个实例变量,其名称分别为 `_firstName` 与 `_lastName`。也可以在类的实现代码里通过 `@synthesize` 语法来指定实例变量的名字. @@ -490,17 +482,7 @@ self.mutableArray = array; @synthesize lastName = _myLastName; @end ``` - -我为了搞清属性是怎么实现的,曾经反编译过相关的代码,他大致生成了五个东西 - - 1. `OBJC_IVAR_$类名$属性名称` :该属性的“偏移量” (offset),这个偏移量是“硬编码” (hardcode),表示该变量距离存放对象的内存区域的起始地址有多远。 - 2. setter 与 getter 方法对应的实现函数 - 2. `ivar_list` :成员变量列表 - 2. `method_list` :方法列表 - 2. `prop_list` :属性列表 - - -也就是说我们每次在增加一个属性,系统都会在 `ivar_list` 中添加一个成员变量的描述,在 `method_list` 中增加 setter 与 getter 方法的描述,在属性列表中增加一个属性的描述,然后计算该属性在对象中的偏移量,然后给出 setter 与 getter 方法对应的实现,在 setter 方法中从偏移量的位置开始赋值,在 getter 方法中从偏移量开始取值,为了能够读取正确字节数,系统对象偏移量的指针类型进行了类型强转. +参考 https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html ###7. @protocol 和 category 中如何使用 @property From 9354dd0405ffc3567a472762af08627179fa4975 Mon Sep 17 00:00:00 2001 From: liruqi Date: Fri, 30 Oct 2015 18:59:57 +0800 Subject: [PATCH 05/14] Clean up --- ...10\357\274\210\344\270\212\357\274\211.md" | 250 +----------------- 1 file changed, 3 insertions(+), 247 deletions(-) diff --git "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" index ef3da7f..8602aa3 100644 --- "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" +++ "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" @@ -4,10 +4,7 @@ #索引 - 1. [风格纠错题](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#1-风格纠错题) - - 1. [优化部分](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#优化部分) - 2. [硬伤部分](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#硬伤部分) + 1. [风格纠错题](#1-风格纠错题) 2. [什么情况使用 weak 关键字,相比 assign 有什么不同?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#2-什么情况使用-weak-关键字相比-assign-有什么不同) 3. [怎么用 copy 关键字?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#3-怎么用-copy-关键字) 4. [这个写法会出什么问题: @property (copy) NSMutableArray *array;](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#4-这个写法会出什么问题-property-copy-nsmutablearray-array) @@ -496,7 +493,7 @@ self.mutableArray = array; 要实现 weak 属性,首先要搞清楚 weak 属性的特点: -> weak 此特质表明该属性定义了一种“非拥有关系” (nonowning relationship)。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此特质同 assign 类似, 然而在属性所指的对象遭到摧毁时,属性值也会清空(nil out)。 +> weak 此特质表明该属性定义了一种“非拥有关系” (nonowning relationship)。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此特质同 assign 类似,然而在属性所指的对象遭到摧毁时,属性值也会清空(nil out)。 那么 runtime 如何实现 weak 变量的自动置nil? @@ -505,248 +502,7 @@ self.mutableArray = array; (注:在下文的《使用runtime Associate方法关联的对象,需要在主对象dealloc的时候释放么?》里给出的“对象的内存销毁时间表”也提到`__weak`引用的解除时间。) -我们可以设计一个函数(伪代码)来表示上述机制: - -`objc_storeWeak(&a, b)`函数: - -`objc_storeWeak`函数把第二个参数--赋值对象(b)的内存地址作为键值key,将第一个参数--weak修饰的属性变量(a)的内存地址(&a)作为value,注册到 weak 表中。如果第二个参数(b)为0(nil),那么把变量(a)的内存地址(&a)从weak表中删除, - -你可以把`objc_storeWeak(&a, b)`理解为:`objc_storeWeak(value, key)`,并且当key变nil,将value置nil。 - -在b非nil时,a和b指向同一个内存地址,在b变nil时,a变nil。此时向a发送消息不会崩溃:在Objective-C中向nil发送消息是安全的。 - -而如果a是由 assign 修饰的,则: -在 b 非 nil 时,a 和 b 指向同一个内存地址,在 b 变 nil 时,a 还是指向该内存地址,变野指针。此时向 a 发送消息极易崩溃。 - - -下面我们将基于`objc_storeWeak(&a, b)`函数,使用伪代码模拟“runtime如何实现weak属性”: - - - - -```Objective-C -// 使用伪代码模拟:runtime如何实现weak属性 -// http://weibo.com/luohanchenyilong/ -// https://github.com/ChenYilong - - id obj1; - objc_initWeak(&obj1, obj); -/*obj引用计数变为0,变量作用域结束*/ - objc_destroyWeak(&obj1); -``` - -下面对用到的两个方法`objc_initWeak`和`objc_destroyWeak`做下解释: - -总体说来,作用是: -通过`objc_initWeak`函数初始化“附有weak修饰符的变量(obj1)”,在变量作用域结束时通过`objc_destoryWeak`函数释放该变量(obj1)。 - -下面分别介绍下方法的内部实现: - -`objc_initWeak`函数的实现是这样的:在将“附有weak修饰符的变量(obj1)”初始化为0(nil)后,会将“赋值对象”(obj)作为参数,调用`objc_storeWeak`函数。 - - - - -```Objective-C -obj1 = 0; -obj_storeWeak(&obj1, obj); -``` - -也就是说: - -> weak 修饰的指针默认值是 nil (在Objective-C中向nil发送消息是安全的) - - - - -然后`obj_destroyWeak`函数将0(nil)作为参数,调用`objc_storeWeak`函数。 - -`objc_storeWeak(&obj1, 0);` - -前面的源代码与下列源代码相同。 - - - -```Objective-C -// 使用伪代码模拟:runtime如何实现weak属性 -// http://weibo.com/luohanchenyilong/ -// https://github.com/ChenYilong - -id obj1; -obj1 = 0; -objc_storeWeak(&obj1, obj); -/* ... obj的引用计数变为0,被置nil ... */ -objc_storeWeak(&obj1, 0); -``` - - -`objc_storeWeak` 函数把第二个参数--赋值对象(obj)的内存地址作为键值,将第一个参数--weak修饰的属性变量(obj1)的内存地址注册到 weak 表中。如果第二个参数(obj)为0(nil),那么把变量(obj1)的地址从 weak 表中删除,在后面的相关一题会详解。 - -使用伪代码是为了方便理解,下面我们“真枪实弹”地实现下: - -> 如何让不使用weak修饰的@property,拥有weak的效果。 - - -我们从setter方法入手: - - ```Objective-C -- (void)setObject:(NSObject *)object -{ - objc_setAssociatedObject(self, "object", object, OBJC_ASSOCIATION_ASSIGN); - [object cyl_runAtDealloc:^{ - _object = nil; - }]; -} - ``` - -也就是有两个步骤: - - 1. 在setter方法中做如下设置: - - - ```Objective-C - objc_setAssociatedObject(self, "object", object, OBJC_ASSOCIATION_ASSIGN); - ``` - - 2. 在属性所指的对象遭到摧毁时,属性值也会清空(nil out)。做到这点,同样要借助 runtime: - - ```Objective-C -//要销毁的目标对象 -id objectToBeDeallocated; -//可以理解为一个“事件”:当上面的目标对象销毁时,同时要发生的“事件”。 -id objectWeWantToBeReleasedWhenThatHappens; -objc_setAssociatedObject(objectToBeDeallocted, - someUniqueKey, - objectWeWantToBeReleasedWhenThatHappens, - OBJC_ASSOCIATION_RETAIN); -``` - -知道了思路,我们就开始实现 `cyl_runAtDealloc` 方法,实现过程分两部分: - -第一部分:创建一个类,可以理解为一个“事件”:当目标对象销毁时,同时要发生的“事件”。借助 block 执行“事件”。 - -// .h文件 - - ```Objective-C -// .h文件 -// http://weibo.com/luohanchenyilong/ -// https://github.com/ChenYilong -// 这个类,可以理解为一个“事件”:当目标对象销毁时,同时要发生的“事件”。借助block执行“事件”。 - -typedef void (^voidBlock)(void); - -@interface CYLBlockExecutor : NSObject - -- (id)initWithBlock:(voidBlock)block; - -@end - ``` - -// .m文件 - - ```Objective-C -// .m文件 -// http://weibo.com/luohanchenyilong/ -// https://github.com/ChenYilong -// 这个类,可以理解为一个“事件”:当目标对象销毁时,同时要发生的“事件”。借助block执行“事件”。 - -#import "CYLBlockExecutor.h" - -@interface CYLBlockExecutor() { - voidBlock _block; -} -@implementation CYLBlockExecutor - -- (id)initWithBlock:(voidBlock)aBlock -{ - self = [super init]; - - if (self) { - _block = [aBlock copy]; - } - - return self; -} - -- (void)dealloc -{ - _block ? _block() : nil; -} - -@end - ``` - -第二部分:核心代码:利用runtime实现`cyl_runAtDealloc`方法 - - ```Objective-C -// CYLNSObject+RunAtDealloc.h文件 -// http://weibo.com/luohanchenyilong/ -// https://github.com/ChenYilong -// 利用runtime实现cyl_runAtDealloc方法 - -#import "CYLBlockExecutor.h" - -const void *runAtDeallocBlockKey = &runAtDeallocBlockKey; - -@interface NSObject (CYLRunAtDealloc) - -- (void)cyl_runAtDealloc:(voidBlock)block; - -@end - - -// CYLNSObject+RunAtDealloc.m文件 -// http://weibo.com/luohanchenyilong/ -// https://github.com/ChenYilong -// 利用runtime实现cyl_runAtDealloc方法 - -#import "CYLNSObject+RunAtDealloc.h" -#import "CYLBlockExecutor.h" - -@implementation NSObject (CYLRunAtDealloc) - -- (void)cyl_runAtDealloc:(voidBlock)block -{ - if (block) { - CYLBlockExecutor *executor = [[CYLBlockExecutor alloc] initWithBlock:block]; - - objc_setAssociatedObject(self, - runAtDeallocBlockKey, - executor, - OBJC_ASSOCIATION_RETAIN); - } -} - -@end - ``` - -使用方法: -导入 - - - ```Objective-C - #import "CYLNSObject+RunAtDealloc.h" - ``` - -然后就可以使用了: - - - ```Objective-C -NSObject *foo = [[NSObject alloc] init]; - -[foo cyl_runAtDealloc:^{ - NSLog(@"正在释放foo!"); -}]; - ``` - - - - - - - -如果对 `cyl_runAtDealloc` 的实现原理有兴趣,可以看下这篇博文 [***Fun With the Objective-C Runtime: Run Code at Deallocation of Any Object***](http://stackoverflow.com/a/31560217/3395008) - +在 ARC 出现之前,weak 并没有自动清空引用的特性。可以参考 [`MAZeroingWeakRef`](https://github.com/mikeash/MAZeroingWeakRef/) 的实现。 ###9. @property中有哪些属性关键字?/ @property 后面可以有哪些修饰符? 属性可以拥有的特质分为四类: From 48dce04e834975bddf5ffbec37d7f0b0405caf5a Mon Sep 17 00:00:00 2001 From: liruqi Date: Fri, 30 Oct 2015 19:03:32 +0800 Subject: [PATCH 06/14] Remove hard link --- ...10\357\274\210\344\270\212\357\274\211.md" | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" index 8602aa3..31a88f7 100644 --- "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" +++ "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" @@ -5,28 +5,28 @@ #索引 1. [风格纠错题](#1-风格纠错题) - 2. [什么情况使用 weak 关键字,相比 assign 有什么不同?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#2-什么情况使用-weak-关键字相比-assign-有什么不同) - 3. [怎么用 copy 关键字?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#3-怎么用-copy-关键字) - 4. [这个写法会出什么问题: @property (copy) NSMutableArray *array;](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#4-这个写法会出什么问题-property-copy-nsmutablearray-array) - 5. [ 如何让自己的类用 copy 修饰符?如何重写带 copy 关键字的 setter?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#5-如何让自己的类用-copy-修饰符如何重写带-copy-关键字的-setter) - 6. [@property 的本质是什么?ivar、getter、setter 是如何生成并添加到这个类中的](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#6-property-的本质是什么ivargettersetter-是如何生成并添加到这个类中的) - 7. [@protocol 和 category 中如何使用 @property](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#7-protocol-和-category-中如何使用-property) - 8. [ runtime 如何实现 weak 属性](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#8-runtime-如何实现-weak-属性) - 9. [@property中有哪些属性关键字?/ @property 后面可以有哪些修饰符?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#9-property中有哪些属性关键字-property-后面可以有哪些修饰符) - 10. [ weak属性需要在dealloc中置nil么?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#10-weak属性需要在dealloc中置nil么) - 11. [@synthesize和@dynamic分别有什么作用?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#11-synthesize和dynamic分别有什么作用) - 12. [ARC下,不显式指定任何属性关键字时,默认的关键字都有哪些?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#12-arc下不显式指定任何属性关键字时默认的关键字都有哪些) - 13. [用@property声明的NSString(或NSArray,NSDictionary)经常使用copy关键字,为什么?如果改用strong关键字,可能造成什么问题?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#13-用property声明的nsstring或nsarraynsdictionary经常使用copy关键字为什么如果改用strong关键字可能造成什么问题) - 1. [对非集合类对象的copy操作](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#1-对非集合类对象的copy操作) - 2. [集合类对象的copy与mutableCopy](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#2集合类对象的copy与mutablecopy) - 14. [@synthesize合成实例变量的规则是什么?假如property名为foo,存在一个名为_foo的实例变量,那么还会自动合成新变量么?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#14-synthesize合成实例变量的规则是什么假如property名为foo存在一个名为_foo的实例变量那么还会自动合成新变量么) - 15. [在有了自动合成属性实例变量之后,@synthesize还有哪些使用场景?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#15-在有了自动合成属性实例变量之后synthesize还有哪些使用场景) - 16. [objc中向一个nil对象发送消息将会发生什么?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#16-objc中向一个nil对象发送消息将会发生什么) - 17. [objc中向一个对象发送消息[obj foo]和objc_msgSend()函数之间有什么关系?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#17-objc中向一个对象发送消息obj-foo和objc_msgsend函数之间有什么关系) - 18. [什么时候会报unrecognized selector的异常?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#18-什么时候会报unrecognized-selector的异常) - 19. [一个objc对象如何进行内存布局?(考虑有父类的情况)](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#19-一个objc对象如何进行内存布局考虑有父类的情况) - 20. [一个objc对象的isa的指针指向什么?有什么作用?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#20-一个objc对象的isa的指针指向什么有什么作用) - 21. [下面的代码输出什么?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md#21-下面的代码输出什么) + 2. [什么情况使用 weak 关键字,相比 assign 有什么不同?](#2-什么情况使用-weak-关键字相比-assign-有什么不同) + 3. [怎么用 copy 关键字?](#3-怎么用-copy-关键字) + 4. [这个写法会出什么问题: @property (copy) NSMutableArray *array;](#4-这个写法会出什么问题-property-copy-nsmutablearray-array) + 5. [ 如何让自己的类用 copy 修饰符?如何重写带 copy 关键字的 setter?](#5-如何让自己的类用-copy-修饰符如何重写带-copy-关键字的-setter) + 6. [@property 的本质是什么?ivar、getter、setter 是如何生成并添加到这个类中的](#6-property-的本质是什么ivargettersetter-是如何生成并添加到这个类中的) + 7. [@protocol 和 category 中如何使用 @property](#7-protocol-和-category-中如何使用-property) + 8. [ runtime 如何实现 weak 属性](#8-runtime-如何实现-weak-属性) + 9. [@property中有哪些属性关键字?/ @property 后面可以有哪些修饰符?](#9-property中有哪些属性关键字-property-后面可以有哪些修饰符) + 10. [ weak属性需要在dealloc中置nil么?](#10-weak属性需要在dealloc中置nil么) + 11. [@synthesize和@dynamic分别有什么作用?](#11-synthesize和dynamic分别有什么作用) + 12. [ARC下,不显式指定任何属性关键字时,默认的关键字都有哪些?](#12-arc下不显式指定任何属性关键字时默认的关键字都有哪些) + 13. [用@property声明的NSString(或NSArray,NSDictionary)经常使用copy关键字,为什么?如果改用strong关键字,可能造成什么问题?](#13-用property声明的nsstring或nsarraynsdictionary经常使用copy关键字为什么如果改用strong关键字可能造成什么问题) + 1. [对非集合类对象的copy操作](#1-对非集合类对象的copy操作) + 2. [集合类对象的copy与mutableCopy](#2集合类对象的copy与mutablecopy) + 14. [@synthesize合成实例变量的规则是什么?假如property名为foo,存在一个名为_foo的实例变量,那么还会自动合成新变量么?](#14-synthesize合成实例变量的规则是什么假如property名为foo存在一个名为_foo的实例变量那么还会自动合成新变量么) + 15. [在有了自动合成属性实例变量之后,@synthesize还有哪些使用场景?](#15-在有了自动合成属性实例变量之后synthesize还有哪些使用场景) + 16. [objc中向一个nil对象发送消息将会发生什么?](#16-objc中向一个nil对象发送消息将会发生什么) + 17. [objc中向一个对象发送消息[obj foo]和objc_msgSend()函数之间有什么关系?](#17-objc中向一个对象发送消息obj-foo和objc_msgsend函数之间有什么关系) + 18. [什么时候会报unrecognized selector的异常?](#18-什么时候会报unrecognized-selector的异常) + 19. [一个objc对象如何进行内存布局?(考虑有父类的情况)](#19-一个objc对象如何进行内存布局考虑有父类的情况) + 20. [一个objc对象的isa的指针指向什么?有什么作用?](#20-一个objc对象的isa的指针指向什么有什么作用) + 21. [下面的代码输出什么?](#21-下面的代码输出什么) ```Objective-C From 8ca28acec5ccf484d6d4ce52fcf88068ae2a33ce Mon Sep 17 00:00:00 2001 From: liruqi Date: Fri, 30 Oct 2015 19:16:44 +0800 Subject: [PATCH 07/14] =?UTF-8?q?weak=E5=B1=9E=E6=80=A7=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E5=9C=A8dealloc=E4=B8=AD=E7=BD=AEnil=E4=B9=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...10\357\274\210\344\270\212\357\274\211.md" | 28 +------------------ 1 file changed, 1 insertion(+), 27 deletions(-) diff --git "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" index 31a88f7..434a1b0 100644 --- "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" +++ "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" @@ -549,37 +549,11 @@ self.mutableArray = array; 3. 不常用的:`nonnull`,`null_resettable`,`nullable` ###10. weak属性需要在dealloc中置nil么? -不需要。 +不需要。weak 属性在 ARC 环境下才会出现。 > 在ARC环境无论是强指针还是弱指针都无需在 dealloc 设置为 nil , ARC 会自动帮我们处理 -即便是编译器不帮我们做这些,weak也不需要在 dealloc 中置nil: - -正如上文的:***runtime 如何实现 weak 属性*** 中提到的: - -我们模拟下 weak 的 setter 方法,应该如下: - - - ```Objective-C -- (void)setObject:(NSObject *)object -{ - objc_setAssociatedObject(self, "object", object, OBJC_ASSOCIATION_ASSIGN); - [object cyl_runAtDealloc:^{ - _object = nil; - }]; -} - ``` - - -也即: - -> 在属性所指的对象遭到摧毁时,属性值也会清空(nil out)。 - - - - - ###11. @synthesize和@dynamic分别有什么作用? From a614da99feb6a0fd6f3578c35fea54b9b70df210 Mon Sep 17 00:00:00 2001 From: liruqi Date: Fri, 30 Oct 2015 19:19:42 +0800 Subject: [PATCH 08/14] =?UTF-8?q?weak=E5=B1=9E=E6=80=A7=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E5=9C=A8dealloc=E4=B8=AD=E7=BD=AEnil=E4=B9=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...7\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" index 434a1b0..65582ae 100644 --- "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" +++ "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" @@ -554,6 +554,7 @@ self.mutableArray = array; > 在ARC环境无论是强指针还是弱指针都无需在 dealloc 设置为 nil , ARC 会自动帮我们处理 +参考[Transitioning to ARC Release Notes](https://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html) ###11. @synthesize和@dynamic分别有什么作用? From 082730beadaf13e9421e97fb99203e3090df9a18 Mon Sep 17 00:00:00 2001 From: liruqi Date: Fri, 30 Oct 2015 19:45:19 +0800 Subject: [PATCH 09/14] Add weak runtime impl link --- ...55\224\346\241\210\357\274\210\344\270\212\357\274\211.md" | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" index 65582ae..475f5a2 100644 --- "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" +++ "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" @@ -500,6 +500,8 @@ self.mutableArray = array; > runtime 对注册的类, 会进行布局,对于 weak 对象会放入一个 hash 表中。 用 weak 指向的对象内存地址作为 key,当此对象的引用计数为0的时候会 dealloc,假如 weak 指向的对象内存地址是a,那么就会以a为键, 在这个 weak 表中搜索,找到所有以a为键的 weak 对象,从而设置为 nil。 +代码实现参考 [`objc4/objc4-647/runtime/objc-weak.mm`](https://opensource.apple.com/source/objc4/objc4-647/runtime/objc-weak.mm) + (注:在下文的《使用runtime Associate方法关联的对象,需要在主对象dealloc的时候释放么?》里给出的“对象的内存销毁时间表”也提到`__weak`引用的解除时间。) 在 ARC 出现之前,weak 并没有自动清空引用的特性。可以参考 [`MAZeroingWeakRef`](https://github.com/mikeash/MAZeroingWeakRef/) 的实现。 @@ -560,7 +562,7 @@ self.mutableArray = array; 1. @property有两个对应的词,一个是 @synthesize,一个是 @dynamic。如果 @synthesize和 @dynamic都没写,那么默认的就是`@syntheszie var = _var;` 2. @synthesize 的语义是如果你没有手动实现 setter 方法和 getter 方法,那么编译器会自动为你加上这两个方法。 - 3. @dynamic 告诉编译器:属性的 setter 与 getter 方法由用户自己实现,不自动生成。(当然对于 readonly 的属性只需提供 getter 即可)。假如一个属性被声明为 @dynamic var,然后你没有提供 @setter方法和 @getter 方法,编译的时候没问题,但是当程序运行到 `instance.var = someVar`,由于缺 setter 方法会导致程序崩溃;或者当运行到 `someVar = var` 时,由于缺 getter 方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。 + 3. @dynamic 告诉编译器:属性的 setter 与 getter 方法由用户自己实现,不自动生成,也不用自动生成对应的实例变量。(当然对于 readonly 的属性只需提供 getter 即可)。假如一个属性被声明为 @dynamic var,然后你没有提供 @setter方法和 @getter 方法,编译的时候没问题,但是当程序运行到 `instance.var = someVar`,由于缺 setter 方法会导致程序崩溃;或者当运行到 `someVar = var` 时,由于缺 getter 方法同样会导致崩溃。参考 [Dynamic Method Resolution](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html)。 ###12. ARC下,不显式指定任何属性关键字时,默认的关键字都有哪些? From 38ddaf63781e27f172b3a69e147075acd4a24d41 Mon Sep 17 00:00:00 2001 From: liruqi Date: Fri, 30 Oct 2015 20:00:01 +0800 Subject: [PATCH 10/14] Clean up --- ...10\357\274\210\344\270\212\357\274\211.md" | 37 +------------------ 1 file changed, 1 insertion(+), 36 deletions(-) diff --git "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" index 475f5a2..4ba8ed4 100644 --- "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" +++ "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\212\357\274\211.md" @@ -845,57 +845,22 @@ NSMutableArray *mCopyArray = [array mutableCopy]; 2. 要么如第17行:使用`@synthesize foo = _foo;` ,关联 @property 与 ivar。 更多信息,请戳- 》[ ***When should I use @synthesize explicitly?*** ](http://stackoverflow.com/a/19821816/3395008) + ###16. objc中向一个nil对象发送消息将会发生什么? 在 Objective-C 中向 nil 发送消息是完全有效的——只是在运行时不会有任何作用: 1. 如果一个方法返回值是一个对象,那么发送给nil的消息将返回0(nil)。例如: - ```Objective-C Person * motherInlaw = [[aPerson spouse] mother]; ``` - - 如果 spouse 对象为 nil,那么发送给 nil 的消息 mother 也将返回 nil。 2. 如果方法返回值为指针类型,其指针大小为小于或者等于sizeof(void*),float,double,long double 或者 long long 的整型标量,发送给 nil 的消息将返回0。 2. 如果方法返回值为结构体,发送给 nil 的消息将返回0。结构体中各个字段的值将都是0。 2. 如果方法的返回值不是上述提到的几种情况,那么发送给 nil 的消息的返回值将是未定义的。 -具体原因如下: - - > objc是动态语言,每个方法在运行时会被动态转为消息发送,即:objc_msgSend(receiver, selector)。 - -那么,为了方便理解这个内容,还是贴一个objc的源代码: - - - -```Objective-C -// runtime.h(类在runtime中的定义) -// http://weibo.com/luohanchenyilong/ -// https://github.com/ChenYilong - -struct objc_class { - Class isa OBJC_ISA_AVAILABILITY; //isa指针指向Meta Class,因为Objc的类的本身也是一个Object,为了处理这个关系,runtime就创造了Meta Class,当给类发送[NSObject alloc]这样消息时,实际上是把这个消息发给了Class Object - #if !__OBJC2__ - Class super_class OBJC2_UNAVAILABLE; // 父类 - const char *name OBJC2_UNAVAILABLE; // 类名 - long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0 - long info OBJC2_UNAVAILABLE; // 类信息,供运行期使用的一些位标识 - long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小 - struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量链表 - struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定义的链表 - struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法缓存,对象接到一个消息会根据isa指针查找消息对象,这时会在method Lists中遍历,如果cache了,常用的方法调用时就能够提高调用的效率。 - struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表 - #endif - } OBJC2_UNAVAILABLE; -``` - -objc在向一个对象发送消息时,runtime库会根据对象的isa指针找到该对象实际所属的类,然后在该类中的方法列表以及其父类方法列表中寻找方法运行,然后在发送消息的时候,objc_msgSend方法不会返回值,所谓的返回内容都是具体调用时执行的。 -那么,回到本题,如果向一个nil对象发送消息,首先在寻找对象的isa指针时就是0地址返回了,所以不会出现任何错误。 - - ###17. objc中向一个对象发送消息[obj foo]和`objc_msgSend()`函数之间有什么关系? 具体原因同上题:该方法编译之后就是`objc_msgSend()`函数调用. From 7dcb9d0b26d32a1fff9610efe61ca20a612331a3 Mon Sep 17 00:00:00 2001 From: liruqi Date: Sat, 31 Oct 2015 16:18:17 +0800 Subject: [PATCH 11/14] Fix hard link --- ...10\357\274\210\344\270\213\357\274\211.md" | 71 +++++++++---------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\213\357\274\211.md" "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\213\357\274\211.md" index 64ae6eb..c52148f 100644 --- "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\213\357\274\211.md" +++ "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\213\357\274\211.md" @@ -2,37 +2,30 @@ [《招聘一个靠谱的 iOS》](http://blog.sunnyxx.com/2015/07/04/ios-interview/)—参考答案(下) -说明:面试题来源是[微博@我就叫Sunny怎么了](http://weibo.com/u/1364395395)的这篇博文:[《招聘一个靠谱的 iOS》](http://blog.sunnyxx.com/2015/07/04/ios-interview/),其中共55题,除第一题为纠错题外,其他54道均为简答题。 - -出题者简介: 孙源(sunnyxx),目前就职于百度,负责百度知道 iOS 客户端的开发工作,对技术喜欢刨根问底和总结最佳实践,热爱分享和开源,维护一个叫 forkingdog 的开源小组。 - -答案为[微博@iOS程序犭袁](http://weibo.com/luohanchenyilong/)整理,未经出题者校对,如有纰漏,请向[微博@iOS程序犭袁](http://weibo.com/luohanchenyilong/)指正。 - ---------- - # 索引 - 1. [ 25. `_objc_msgForward` 函数是做什么的,直接调用它将会发生什么?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#25-_objc_msgforward函数是做什么的直接调用它将会发生什么) - 2. [26. runtime如何实现weak变量的自动置nil?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#26-runtime如何实现weak变量的自动置nil) - 3. [27. 能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#27-能否向编译后得到的类中增加实例变量能否向运行时创建的类中添加实例变量为什么) - 4. [28. runloop和线程有什么关系?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#28-runloop和线程有什么关系) - 5. [29. runloop的mode作用是什么?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#29-runloop的mode作用是什么) - 6. [30. 以+ scheduledTimerWithTimeInterval...的方式触发的timer,在滑动页面上的列表时,timer会暂定回调,为什么?如何解决?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#30-以-scheduledtimerwithtimeinterval的方式触发的timer在滑动页面上的列表时timer会暂定回调为什么如何解决) - 7. [31. 猜想runloop内部是如何实现的?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#31-猜想runloop内部是如何实现的) - 8. [32. objc使用什么机制管理对象内存?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#32-objc使用什么机制管理对象内存) - 9. [33. ARC通过什么方式帮助开发者管理内存?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#33-arc通过什么方式帮助开发者管理内存) - 10. [34. 不手动指定autoreleasepool的前提下,一个autorealese对象在什么时刻释放?(比如在一个vc的viewDidLoad中创建)](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#34-不手动指定autoreleasepool的前提下一个autorealese对象在什么时刻释放比如在一个vc的viewdidload中创建) - 11. [35. BAD_ACCESS在什么情况下出现?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#35-bad_access在什么情况下出现) - 12. [36. 苹果是如何实现autoreleasepool的?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#36-苹果是如何实现autoreleasepool的) - 13. [37. 使用block时什么情况会发生引用循环,如何解决?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#37-使用block时什么情况会发生引用循环如何解决) - 14. [38. 在block内如何修改block外部变量?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#38-在block内如何修改block外部变量) - 15. [39. 使用系统的某些block api(如UIView的block版本写动画时),是否也考虑引用循环问题?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#39-使用系统的某些block-api如uiview的block版本写动画时是否也考虑引用循环问题) - 16. [40. GCD的队列(dispatch_queue_t)分哪两种类型?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#40-gcd的队列dispatch_queue_t分哪两种类型) - 17. [41. 如何用GCD同步若干个异步调用?(如根据若干个url异步加载多张图片,然后在都下载完成后合成一张整图)](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#41-如何用gcd同步若干个异步调用如根据若干个url异步加载多张图片然后在都下载完成后合成一张整图) - 18. [42. dispatch_barrier_async的作用是什么?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#42-dispatch_barrier_async的作用是什么) - 19. [43. 苹果为什么要废弃dispatch_get_current_queue?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#43-苹果为什么要废弃dispatch_get_current_queue) - 0. [44. 以下代码运行结果如何?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#44-以下代码运行结果如何) + 1. [ 25. `_objc_msgForward` 函数是做什么的,直接调用它将会发生什么?](#25-_objc_msgforward函数是做什么的直接调用它将会发生什么) + 2. [26. runtime如何实现weak变量的自动置nil?](#26-runtime如何实现weak变量的自动置nil) + 3. [27. 能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么?](#27-能否向编译后得到的类中增加实例变量能否向运行时创建的类中添加实例变量为什么) + 4. [28. runloop和线程有什么关系?](#28-runloop和线程有什么关系) + 5. [29. runloop的mode作用是什么?](#29-runloop的mode作用是什么) + 6. [30. 以+ scheduledTimerWithTimeInterval...的方式触发的timer,在滑动页面上的列表时,timer会暂定回调,为什么?如何解决?](#30-以-scheduledtimerwithtimeinterval的方式触发的timer在滑动页面上的列表时timer会暂定回调为什么如何解决) + 7. [31. 猜想runloop内部是如何实现的?](#31-猜想runloop内部是如何实现的) + 8. [32. objc使用什么机制管理对象内存?](#32-objc使用什么机制管理对象内存) + 9. [33. ARC通过什么方式帮助开发者管理内存?](#33-arc通过什么方式帮助开发者管理内存) + 10. [34. 不手动指定autoreleasepool的前提下,一个autorealese对象在什么时刻释放?(比如在一个vc的viewDidLoad中创建)](#34-不手动指定autoreleasepool的前提下一个autorealese对象在什么时刻释放比如在一个vc的viewdidload中创建) + 11. [35. BAD_ACCESS在什么情况下出现?](#35-bad_access在什么情况下出现) + 12. [36. 苹果是如何实现autoreleasepool的?](#36-苹果是如何实现autoreleasepool的) + 13. [37. 使用block时什么情况会发生引用循环,如何解决?](#37-使用block时什么情况会发生引用循环如何解决) + 14. [38. 在block内如何修改block外部变量?](#38-在block内如何修改block外部变量) + 15. [39. 使用系统的某些block api(如UIView的block版本写动画时),是否也考虑引用循环问题?](#39-使用系统的某些block-api如uiview的block版本写动画时是否也考虑引用循环问题) + 16. [40. GCD的队列(dispatch_queue_t)分哪两种类型?](#40-gcd的队列dispatch_queue_t分哪两种类型) + 17. [41. 如何用GCD同步若干个异步调用?(如根据若干个url异步加载多张图片,然后在都下载完成后合成一张整图)](#41-如何用gcd同步若干个异步调用如根据若干个url异步加载多张图片然后在都下载完成后合成一张整图) + 18. [42. dispatch_barrier_async的作用是什么?](#42-dispatch_barrier_async的作用是什么) + 19. [43. 苹果为什么要废弃dispatch_get_current_queue?](#43-苹果为什么要废弃dispatch_get_current_queue) + 0. [44. 以下代码运行结果如何?](#44-以下代码运行结果如何) ```Objective-C - (void)viewDidLoad @@ -46,17 +39,17 @@ } ``` - 1. [45. addObserver:forKeyPath:options:context:各个参数的作用分别是什么,observer中需要实现哪个方法才能获得KVO回调?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#45-addobserverforkeypathoptionscontext各个参数的作用分别是什么observer中需要实现哪个方法才能获得kvo回调) - 2. [46. 如何手动触发一个value的KVO](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#46-如何手动触发一个value的kvo) - 3. [47. 若一个类有实例变量 NSString *_foo ,调用setValue:forKey:时,可以以foo还是 _foo 作为key?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#47-若一个类有实例变量-nsstring-_foo-调用setvalueforkey时可以以foo还是-_foo-作为key) - 4. [48. KVC的keyPath中的集合运算符如何使用?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#48-kvc的keypath中的集合运算符如何使用) - 5. [49. KVC和KVO的keyPath一定是属性么?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#49-kvc和kvo的keypath一定是属性么) - 6. [50. 如何关闭默认的KVO的默认实现,并进入自定义的KVO实现?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#50-如何关闭默认的kvo的默认实现并进入自定义的kvo实现) - 7. [51. apple用什么方式实现对一个对象的KVO?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#51-apple用什么方式实现对一个对象的kvo) - 8. [52. IBOutlet连出来的视图属性为什么可以被设置成weak?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#52-iboutlet连出来的视图属性为什么可以被设置成weak) - 9. [53. IB中User Defined Runtime Attributes如何使用?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#53-ib中user-defined-runtime-attributes如何使用) - 0. [54. 如何调试BAD_ACCESS错误](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#54-如何调试bad_access错误) - 1. [55. lldb(gdb)常用的调试命令?](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md#55-lldbgdb常用的调试命令) + 1. [45. addObserver:forKeyPath:options:context:各个参数的作用分别是什么,observer中需要实现哪个方法才能获得KVO回调?](#45-addobserverforkeypathoptionscontext各个参数的作用分别是什么observer中需要实现哪个方法才能获得kvo回调) + 2. [46. 如何手动触发一个value的KVO](#46-如何手动触发一个value的kvo) + 3. [47. 若一个类有实例变量 NSString *_foo ,调用setValue:forKey:时,可以以foo还是 _foo 作为key?](#47-若一个类有实例变量-nsstring-_foo-调用setvalueforkey时可以以foo还是-_foo-作为key) + 4. [48. KVC的keyPath中的集合运算符如何使用?](#48-kvc的keypath中的集合运算符如何使用) + 5. [49. KVC和KVO的keyPath一定是属性么?](#49-kvc和kvo的keypath一定是属性么) + 6. [50. 如何关闭默认的KVO的默认实现,并进入自定义的KVO实现?](#50-如何关闭默认的kvo的默认实现并进入自定义的kvo实现) + 7. [51. apple用什么方式实现对一个对象的KVO?](#51-apple用什么方式实现对一个对象的kvo) + 8. [52. IBOutlet连出来的视图属性为什么可以被设置成weak?](#52-iboutlet连出来的视图属性为什么可以被设置成weak) + 9. [53. IB中User Defined Runtime Attributes如何使用?](#53-ib中user-defined-runtime-attributes如何使用) + 0. [54. 如何调试BAD_ACCESS错误](#54-如何调试bad_access错误) + 1. [55. lldb(gdb)常用的调试命令?](#55-lldbgdb常用的调试命令) @@ -956,4 +949,4 @@ KVO 在实现中通过 ` isa 混写(isa-swizzling)` 把这个对象的 isa Posted by [微博@iOS程序犭袁](http://weibo.com/luohanchenyilong/) -原创文章,版权声明:自由转载-非商用-非衍生-保持署名 | [Creative Commons BY-NC-ND 3.0](http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh) \ No newline at end of file +原创文章,版权声明:自由转载-非商用-非衍生-保持署名 | [Creative Commons BY-NC-ND 3.0](http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh) From fe6813d89cdd1a28c61190812195c6aafce74e77 Mon Sep 17 00:00:00 2001 From: liruqi Date: Sat, 31 Oct 2015 16:56:33 +0800 Subject: [PATCH 12/14] Clean up --- ...10\357\274\210\344\270\213\357\274\211.md" | 82 +------------------ 1 file changed, 1 insertion(+), 81 deletions(-) diff --git "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\213\357\274\211.md" "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\213\357\274\211.md" index c52148f..1fa6db9 100644 --- "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\213\357\274\211.md" +++ "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\213\357\274\211.md" @@ -332,87 +332,7 @@ typedef void (*voidIMP)(id, SEL, ...) > runtime 对注册的类, 会进行布局,对于 weak 对象会放入一个 hash 表中。 用 weak 指向的对象内存地址作为 key,当此对象的引用计数为0的时候会 dealloc,假如 weak 指向的对象内存地址是a,那么就会以a为键, 在这个 weak 表中搜索,找到所有以a为键的 weak 对象,从而设置为 nil。 -在[上篇](https://github.com/ChenYilong/iOSInterviewQuestions)中的《runtime 如何实现 weak 属性》有论述。(注:在[上篇](https://github.com/ChenYilong/iOSInterviewQuestions)的《使用runtime Associate方法关联的对象,需要在主对象dealloc的时候释放么?》里给出的“对象的内存销毁时间表”也提到`__weak`引用的解除时间。) - -我们可以设计一个函数(伪代码)来表示上述机制: - -`objc_storeWeak(&a, b)`函数: - -`objc_storeWeak`函数把第二个参数--赋值对象(b)的内存地址作为键值key,将第一个参数--weak修饰的属性变量(a)的内存地址(&a)作为value,注册到 weak 表中。如果第二个参数(b)为0(nil),那么把变量(a)的内存地址(&a)从weak表中删除, - -你可以把`objc_storeWeak(&a, b)`理解为:`objc_storeWeak(value, key)`,并且当key变nil,将value置nil。 - -在b非nil时,a和b指向同一个内存地址,在b变nil时,a变nil。此时向a发送消息不会崩溃:在Objective-C中向nil发送消息是安全的。 - -而如果a是由assign修饰的,则: -在b非nil时,a和b指向同一个内存地址,在b变nil时,a还是指向该内存地址,变野指针。此时向a发送消息极易崩溃。 - - -下面我们将基于`objc_storeWeak(&a, b)`函数,使用伪代码模拟“runtime如何实现weak属性”: - - - - -```Objective-C -// 使用伪代码模拟:runtime如何实现weak属性 -// http://weibo.com/luohanchenyilong/ -// https://github.com/ChenYilong - - id obj1; - objc_initWeak(&obj1, obj); -/*obj引用计数变为0,变量作用域结束*/ - objc_destroyWeak(&obj1); -``` - -下面对用到的两个方法`objc_initWeak`和`objc_destroyWeak`做下解释: - -总体说来,作用是: -通过`objc_initWeak`函数初始化“附有weak修饰符的变量(obj1)”,在变量作用域结束时通过`objc_destoryWeak`函数释放该变量(obj1)。 - -下面分别介绍下方法的内部实现: - -`objc_initWeak`函数的实现是这样的:在将“附有weak修饰符的变量(obj1)”初始化为0(nil)后,会将“赋值对象”(obj)作为参数,调用`objc_storeWeak`函数。 - - - - -```Objective-C -obj1 = 0; -obj_storeWeak(&obj1, obj); -``` - -也就是说: - -> weak 修饰的指针默认值是 nil (在Objective-C中向nil发送消息是安全的) - - - - -然后`obj_destroyWeak`函数将0(nil)作为参数,调用`objc_storeWeak`函数。 - -`objc_storeWeak(&obj1, 0);` - -前面的源代码与下列源代码相同。 - - - -```Objective-C -// 使用伪代码模拟:runtime如何实现weak属性 -// http://weibo.com/luohanchenyilong/ -// https://github.com/ChenYilong - -id obj1; -obj1 = 0; -objc_storeWeak(&obj1, obj); -/* ... obj的引用计数变为0,被置nil ... */ -objc_storeWeak(&obj1, 0); -``` - - -`objc_storeWeak`函数把第二个参数--赋值对象(obj)的内存地址作为键值,将第一个参数--weak修饰的属性变量(obj1)的内存地址注册到 weak 表中。如果第二个参数(obj)为0(nil),那么把变量(obj1)的地址从weak表中删除。 - - - +runtime 实现代码:https://opensource.apple.com/source/objc4/objc4-647/runtime/objc-weak.mm ###27. 能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么? From 365fe63d2cd5d554003a203291f53c2b9862b4c0 Mon Sep 17 00:00:00 2001 From: liruqi Date: Mon, 2 Nov 2015 09:05:39 +0800 Subject: [PATCH 13/14] Correct answer for resolving block reference cycle --- ...346\241\210\357\274\210\344\270\213\357\274\211.md" | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\213\357\274\211.md" "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\213\357\274\211.md" index 1fa6db9..165d382 100644 --- "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\213\357\274\211.md" +++ "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\213\357\274\211.md" @@ -550,13 +550,13 @@ autoreleasepool 以一个队列数组的形式实现,主要通过下列三个函 ![enter image description here](http://i60.tinypic.com/15mfj11.jpg) ###37. 使用block时什么情况会发生引用循环,如何解决? -一个对象中强引用了block,在block中又使用了该对象,就会发射循环引用。 -解决方法是将该对象使用__weak或者__block修饰符修饰之后再在block中使用。 +一个对象中强引用了block,在block中又使用了该对象,就会产生循环引用。 +解决方法是,ARC 环境下,在 block 外部用 `__weak` 修饰符创建弱引用对象,再在block中使用弱引用对象。Manual reference counting 环境下,用 `__block` 修饰符创建弱引用对象。如果希望兼容 iOS 4 或者 OS X 10.6,就用 `__block` 修饰符,并在 block 代码总设置 `__block` 变量为 `nil`。 +> In manual reference counting mode, __block id x; has the effect of not retaining x. In ARC mode, __block id x; defaults to retaining x (just like all other values). To get the manual reference counting mode behavior under ARC, you could use __unsafe_unretained __block id x;. As the name __unsafe_unretained implies, however, having a non-retained variable is dangerous (because it can dangle) and is therefore discouraged. Two better options are to either use __weak (if you don’t need to support iOS 4 or OS X v10.6), or set the __block value to nil to break the retain cycle. + +参考:[Use Lifetime Qualifiers to Avoid Strong Reference Cycles](https://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226-CH1-SW9) - 1. id weak weakSelf = self; - 或者 weak __typeof(&*self)weakSelf = self该方法可以设置宏 - 2. id __block weakSelf = self; ###38. 在block内如何修改block外部变量? 默认情况下,在block中访问的外部变量是复制过去的,即:**写操作不对原变量生效**。但是你可以加上`__block`来让其写操作生效,示例代码如下: From 07dc88c0c0f795f6c5eb9a1d5904e2cbbe9921e7 Mon Sep 17 00:00:00 2001 From: liruqi Date: Mon, 2 Nov 2015 10:17:09 +0800 Subject: [PATCH 14/14] Add English description for dispatch_barrier_async --- ...346\241\210\357\274\210\344\270\213\357\274\211.md" | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\213\357\274\211.md" "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\213\357\274\211.md" index 165d382..cd72e13 100644 --- "a/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\213\357\274\211.md" +++ "b/01\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210/\343\200\212\346\213\233\350\201\230\344\270\200\344\270\252\351\235\240\350\260\261\347\232\204iOS\343\200\213\351\235\242\350\257\225\351\242\230\345\217\202\350\200\203\347\255\224\346\241\210\357\274\210\344\270\213\357\274\211.md" @@ -565,12 +565,9 @@ autoreleasepool 以一个队列数组的形式实现,主要通过下列三个函 void (^foo)(void) = ^{ a = 1; } - f00(); + foo(); //这里,a的值被修改为1 - -参考链接:[微博@唐巧_boy](http://weibo.com/tangqiaoboy)的著作《iOS开发进阶》中的第11.2.3章节 - ###39. 使用系统的某些block api(如UIView的block版本写动画时),是否也考虑引用循环问题? 系统的某些block api中,UIView的block版本写动画时不需要考虑,但也有一些api 需要考虑: @@ -651,10 +648,11 @@ dispatch_group_notify(group, dispatch_get_main_queue(), ^{ 在并行队列中,为了保持某些任务的顺序,需要等待一些任务完成后才能继续进行,使用 barrier 来等待之前任务完成,避免数据竞争等问题。 `dispatch_barrier_async` 函数会等待追加到Concurrent Dispatch Queue并行队列中的操作全部执行完之后,然后再执行 `dispatch_barrier_async` 函数追加的处理,等 `dispatch_barrier_async` 追加的处理执行结束之后,Concurrent Dispatch Queue才恢复之前的动作继续执行。 -打个比方:比如你们公司周末跟团旅游,高速休息站上,司机说:大家都去上厕所,速战速决,上完厕所就上高速。超大的公共厕所,大家同时去,程序猿很快就结束了,但程序媛就可能会慢一些,即使你第一个回来,司机也不会出发,司机要等待所有人都回来后,才能出发。 `dispatch_barrier_async` 函数追加的内容就如同 “上完厕所就上高速”这个动作。 +> Calls to this function always return immediately after the block has been submitted and never wait for the block to be invoked. When the barrier block reaches the front of a private concurrent queue, it is not executed immediately. Instead, the queue waits until its currently executing blocks finish executing. At that point, the barrier block executes by itself. Any blocks submitted after the barrier block are not executed until the barrier block completes. -(注意:使用 `dispatch_barrier_async` ,该函数只能搭配自定义并行队列 `dispatch_queue_t` 使用。不能使用: `dispatch_get_global_queue` ,否则 `dispatch_barrier_async` 的作用会和 `dispatch_async` 的作用一模一样。 ) +> The queue you specify should be a concurrent queue that you create yourself using the dispatch_queue_create function. If the queue you pass to this function is a serial queue or one of the global concurrent queues, this function behaves like the dispatch_async function. +参考 [dispatch_barrier_async](https://developer.apple.com/library/prerelease/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/index.html#//apple_ref/c/func/dispatch_barrier_async) ###43. 苹果为什么要废弃`dispatch_get_current_queue`?