通用规则书上都讲了,无非就是谁持有谁释放。我开始也认为Objective-C内存管理规则挺简单明了。可是在项目开发中确遇到了一些问题。    做的项目是基于网络的小游戏,大概说说系统结构:UI管理和数据是分离的,通过控制器作为联系(由控制器创建UI管理类和数据类)。底层有负责收发消息的线程,收到消息后拆包转发给控制器。控制器先处理数据,然后调用UI管理模块将处理后的数据在界面上展现。当存在UI操作的时候,调用控制器,然后由控制器处理数据后发送给服务器。下面是遇到的内存问题:1.循环引用所导致的无法释放的问题:
    这里存在循环引用的问题,即控制器持有了UI管理类的对象引用,由于UI操作需要回调控制器,这时UI管理类又需要持有控制器的引用。当创建控制器的方法需要释放控制器时,由于UI管理器仍然持有控制器的一个引用,所以控制器对象无法被释放。    那么如何解决这种问题呢:可以尝试在存在循环引用的时候使用弱引用,即不增加对象的引用计数器,当然也不能释放了;可以创建1个stop方法负责主动清理控制器内部持有的引用,并在release之前调用。    其实官方类库里面就存在了很多循环引用的问题,最典型的就是Delegate,几乎所有的Delegate都使用的是弱引用,这点要非常注意。2.Delegate的弱引用引发的问题:
    看下面的代码:TestDelegate* delegate = [[TestDelegate alloc] init];  
UIAlertView* alertV = [[UIAlertView alloc] initWithTitle:@"title"  
                                                 message:@"message"  
                                                delegate:delegate  
                                       cancelButtonTitle:@"cancel"  
                                       otherButtonTitles:@"ok",nil];  
NSLog(@"retainCount:%d",[delegate retainCount]);  
[alertV show];  
[alertV release];  
  
[delegate release];  
    如果是一个初学者,你会惊奇的发现输出的retainCount等于1,点击按钮的时候程序当然要毫不犹豫的报错了。这问题好像没有简单的办法解决。只能靠程序员自己持有对象,然后再在合适的时机释放了。    好像一般的Deleage和Target都不会持有对象引用,但是NSTimer会持有。这只能靠用的时候去尝试了。就算总结出来也没什么意义。
    不知道是不是基础没有学好,我看书的时候是没有见到有讲这些问题的。不知道大家有没有遇到类似的问题,期待大家的补充和指导。
    原文地址:http://blog.csdn.net/waynell/article/details/6672428

解决方案 »

  1.   

    我觉得可能一个被委派的对象要么就是全局的,要么就是局部的,全局的话当然不需要在让当前对象委派的时候持有了,比如appdelegate,但是局部的需要委派的对象一般都会委派到自己上,像你上面写的代码如果delegae:self肯定就没问题了,没有必要在新建一个对象,再委派到其他对象上。不知道苹果当初设计时是怎么考虑的
      

  2.   

    看来csdn里做ios的大侠真的很少,帖子搁了一天没人回还在首页呢!
      

  3.   

    你在上面不是alloc 你的TestDelegate对象吗?
    retain 计数当然会是1咯。是1也不会有问题啊,这样你下面才能release 它了而且上面的代码运行也是没有问题的啊,点击也是可以的。哪道是我理解错了?
      

  4.   

    你试一下就知道了。
    UIAlertView的delegate指向了TestDelegate对象,但是没有持有他TestDelegate的计数仍然为1,调用release后计数为0。但是对话框还在屏幕上显示,这时点击对话框上的按钮会调用被释放的TestDelegate导致错误。
      

  5.   

    最新的sdk已经不需要自己retain、release了,编译器给你自动处理了
      

  6.   

    什么版本?我怎么觉得不太可能呢,java还是通过虚拟机做复杂的运算才做到自动释放,只听说过做mac开发的时候有自动释放,可是还没有听说过编译器能处理这个问题。难道苹果能这么牛?
      

  7.   

    sdk5好像真的自动管理内存了 楼主 我是新手没有你那样写过 估计是[delegate release];  的错
      

  8.   

    IOS 5  ARC
    你可以到https://developer.apple.com/icloud/documentation/里看What's New in iOS
      

  9.   

    另外,我好奇,为什么点击按钮得时候会报错,为什么我写得Demo没报错,你得Demo有问题?
      

  10.   

    委托方法要新创建,别的地方不存在对其的引用。设置UIAlertView的委托后将其释放,然后点击就会有问题。
      

  11.   

    一般情况下, 所有的委托(delegate), 在设置时.
    不会进行 [delegate retain], 因为声明的都是 assign 类型的.TestDelegate* delegate = [[TestDelegate alloc] init];  
    UIAlertView* alertV = [[UIAlertView alloc] initWithTitle:@"title"  
                                                     message:@"message"  
                                                    delegate:delegate  
                                           cancelButtonTitle:@"cancel"  
                                           otherButtonTitles:@"ok",nil];  
    NSLog(@"retainCount:%d",[delegate retainCount]);  
    [alertV show];  
    [alertV release];  
      
    [delegate release];  所以这种写法是错误的.
    你的委托对象还没有使用就已经被释放掉了. 
    但是Alert并不知道delegate被释放, 又产生的调用, 导致程序崩溃.