记录下前两天的一次讨论,源于网络库YTKNetwork中“YTKRequest.m”的- start方法其中的几行代码:
1 | - (void)start { |
看起来比较有违常理,所以和猿题库的@晨钰Lancy,@唐巧以及网易的@老汉一起讨论了下这个问题。
具体的问题大概是这样:
YTKRequest对象,将自己作为其delegateYTKRequest的- start方法发起网络请求- requestFinished:中执行了self.request = nil;YTKRequest中,- start方法在回调完- requestFinished:后BAD_ACCESS了也就是说,- start方法还未返回时,self就被外部释放了。作者发现了这个潜在的问题,所以在方法局部增设了一个strongSelf的强引用来保证self的生命周期延续到方法结束。问题是解决了,但是更希望知道原因。
简化说明就是:
1 | - (void)foo { |
现在想想还是比较不符合常理,入参的self居然不能保证这个函数执行完成。后来查阅了下文档,发现是ARC的(gao)机(de)制(gui),clang的《这篇ARC文档》中有明确的解释,总结如下:
unsafe_unretained的,也就是说,入参的self被表示为:(init系列方法的self除外)1 | - (void)start { |
1 | - (void)start { |
优化了的性能还真是比较可观。
而且,ARC也用了挺多方法来避免开发者进行额外的引用计数控制,比如方法的命名约定,通过判断方法是否以如init,alloc,new,copy等关键字开头来决定其内存管理方式。
One more thing
在写test时发现,下面两种调用方法会导致不同结果:
1 | - (void)viewDidLoad { |
因为self.request是一次方法调用,返回的结果被objc_retainAutoreleasedReturnValue方法在局部进行了一次强引用,关于这个方法可以看之前写过的关于Autorelease的《这篇文章》
记录下前两天的一次讨论,源于网络库YTKNetwork中“YTKRequest.m”的- start方法其中的几行代码:
1 | - (void)start { |
看起来比较有违常理,所以和猿题库的@晨钰Lancy,@唐巧以及网易的@老汉一起讨论了下这个问题。
具体的问题大概是这样:
YTKRequest对象,将自己作为其delegateYTKRequest的- start方法发起网络请求- requestFinished:中执行了self.request = nil;YTKRequest中,- start方法在回调完- requestFinished:后BAD_ACCESS了也就是说,- start方法还未返回时,self就被外部释放了。作者发现了这个潜在的问题,所以在方法局部增设了一个strongSelf的强引用来保证self的生命周期延续到方法结束。问题是解决了,但是更希望知道原因。
简化说明就是:
1 | - (void)foo { |
现在想想还是比较不符合常理,入参的self居然不能保证这个函数执行完成。后来查阅了下文档,发现是ARC的(gao)机(de)制(gui),clang的《这篇ARC文档》中有明确的解释,总结如下:
unsafe_unretained的,也就是说,入参的self被表示为:(init系列方法的self除外)1 | - (void)start { |
1 | - (void)start { |
优化了的性能还真是比较可观。
而且,ARC也用了挺多方法来避免开发者进行额外的引用计数控制,比如方法的命名约定,通过判断方法是否以如init,alloc,new,copy等关键字开头来决定其内存管理方式。
One more thing
在写test时发现,下面两种调用方法会导致不同结果:
1 | - (void)viewDidLoad { |
因为self.request是一次方法调用,返回的结果被objc_retainAutoreleasedReturnValue方法在局部进行了一次强引用,关于这个方法可以看之前写过的关于Autorelease的《这篇文章》