百度地图API里retain cycle的疑问

morpheus1984 发布于 2013年08月19日 | 更新于 2013年08月22日
无人欣赏。

公司项目里有个定位的功能,决定采用百度地图API来做这个。然后看demo的时候发现一个奇怪的地方:@property (nonatomic, retain) id<BMKMapViewDelegate> delegate; 不太明白为什么这里的delegate要用retain 虽然在注释里也说明了 “/// 地图View的Delegate,此处记得不用的时候需要置nil,否则影响内存的释放 ” 我想问下有木有哪位大神这么用过?为什么要这么用呢?什么样的情况下这么用,释放的时候注意哪些才能不内存泄露。拜托了。@tinyfool,@sycx老师有空的话也来看看吧。 上面这个属性是在BMKMapView这个类里面的

共21条回复
btxkenshin 回复于 2013年08月19日

不是说delegate就一定要用assign修饰的,这个看情况,有时候基于一些特殊原因delegate也是需要retain。比如官方的NSURLConnection就是一个典型retain了delegate的例子

terryso 回复于 2013年08月19日

的确不明白他为啥要设计为retain,我觉得这里完全可以使用assign就可以了。 这里用retain简直就是专门给开发者找麻烦。。。

sycx 回复于 2013年08月19日

我觉得这里用retain应该属于设计失误,或者手滑写错...

用retain的话.... 想想都觉着用起来绝对很受罪...

terryso 回复于 2013年08月19日

@sycx 我看了头文件,好多地方的delegate都retain,应该不是错手

morpheus1984 回复于 2013年08月19日

相信就是这么设计的,总不能理解成百度工程师垃圾不知道delegate用assign吧。一楼楼长说“ 有时候基于一些特殊原因delegate也是需要retain。比如官方的NSURLConnection就是一个典型retain了delegate的例子”我在想如果真是这样,那是什么样的特殊原因呢?@sycx @btxkenshin @terryso @tinyfool 各位大神 你们怎么看?

terryso 回复于 2013年08月19日

@morpheus198 我看不到NSURLConnection哪里用了retain的delegate?

morpheus1984 回复于 2013年08月19日

@terryso 我在文档里看到了这么一句话:“Note: During a download the connection maintains a strong reference to the delegate. It releases that strong reference when the connection finishes loading, fails, or is canceled.”

terryso 回复于 2013年08月19日

@morpheus198 嗯,我试验了一下,NSURLConnection的确是会retain它的delegate。不过我想那是因为,NSURLConnection没有一个delegate属性,你必须通过初始化方法把delegate对象传进去,这样NSURLConnection自己就必须retain delegate留来自己用,并且NSURLConnection在请求结束之后,它会自己release它的delegate,这样调用方就不用自己release。 而BMKMapView是有一个delegate属性的,加了retain就会有可能导致retain cycle问题,搞得调用方很麻烦。

terryso 回复于 2013年08月19日

这是我的理解,不知道是否正确,请各位大神拍砖。。。

Elden 回复于 2013年08月19日

GPS定位跟网络下载地图信息都是异步的,用assign可能会遇到调用者提前释放导致crash。

terryso 回复于 2013年08月19日

@Elden 那也应该学NSURLConnection这样,自己retain,自己release,不应该搞个retain属性,搞得使用者那么难受。

morpheus1984 回复于 2013年08月20日

@Elden 有一点我想不通,如果是因为异步的问题的话,那开源库ASIHTTPRequest里面异步网络请求的回调函数也是用delegate来调用啊,源码里面的delegate就是用assign的。还是说我对ASIHTTPRequest开源库理解的不够,你觉得呢?@terryso,@tinyfool @sycx

Elden 回复于 2013年08月20日

@morpheus198 如果用异步请求,ASIHTTPRequest明确要求在释放之前调用[request clearDelegatesAndCancel]

http://allseeing-i.com/ASIHTTPRequest/How-to-use

morpheus1984 回复于 2013年08月20日

@Elden ASIHTTPRequest在dealloc函数里调用clearDelegatesAndCancel,这个我知道,问题这跟Delegate用retain或assign没有关系,百度API明确说明了不用的时候要置nil,给的demo也是在willDidDisappear函数里调用setDelegate:nil。那么用不用retain和是不是异步请求是不是没有关系呢?我的疑问在这里,当然也许是我没想通。

btxkenshin 回复于 2013年08月20日

@morpheus1984 ASI最早版本当delegate提前释放时候是会crash的,原因就是delegate是assign的,而当时版本的cancel里没有对delegate进行处理,当delegate本身被释放了后ASI还去访问了,导致crash,后来版本专门更新了一个clearDelegateAndCancel的方法

morpheus1984 回复于 2013年08月20日

@btxkenshin 感谢回答,clearDelegateAndCancel对于delegate的处理就是set为nil,而delegate本身还是assign的,回到我们最初的疑问,是不是说异步的时候需要考虑delegate提前释放所以要有一个方法将delegate = nil,但是这和delegate是否用retain无关。换句话说假设今天我写了一段代码,为了防止异步导致delegate提前释放而在dealloc里面将delegate = nil 就可以了。这么理解对么?

terryso 回复于 2013年08月20日

@morpheus198 你说得没错。 如果你使用ARC的话,把delegate由assign设置为weak的话,你连在dealloc里把delegate设置为nil这步都可以省了。

btxkenshin 回复于 2013年08月21日

@terryso 所以还是ARC好,项目转成ARC后感觉都流畅了些哈哈

terryso 回复于 2013年08月21日

@btxkenshin ARC好是好,但一开始还要学手动管理内存,否则有时碰到某些坑你根本不知道是为啥形成的。 另外Core API 还是需要手工管理内存。

morpheus1984 回复于 2013年08月21日

我始终觉得百度API 那个问题如果说是设计问题,太诡异了。百度工程师的水平能写架构的不可能这么坑。我已经将问题提交了,不知道可有答复。这里有木有认识百度同行的童鞋能否帮忙给问下呢,或者知道的帮忙给解释下。不吝感激啊。@tinyfool

btxkenshin 回复于 2013年08月22日

@terryso 这是自然,非ARC用了两年了,切过来以后感觉世界清净了许多。 @morpheus198 对于这个问题我的个人理解其实两种都行,但是什么情况下更需要使用retain自己也没有切身体会,有消息了麻烦分享下啊嘿嘿

本帖有21个回复,因为您没有注册或者登录本站,所以,只能看到本帖的10条回复。如果想看到全部回复,请注册或者登录本站。

登录 或者 注册
[顶 楼]
|
|
[底 楼]
|
|
[首 页]