调这种问题有一个技巧,你可以子类化一个UIButton,然后在release和retain等方法里打断点

解决方案 »

  1.   

    你这个为retaincount为2,原因可能是虽然btn   release掉了,但是view还没有release,系统暂时把btn放到了autorelease里面了,当view释放的时候btn才会跟着释放
      

  2.   

    调试程序在viewDidLoad也不调用,你凭直觉网上写的啊。
    就算是正确的,在ARC内存管理中,引用计数是由系统自动释放的,
    你代码也写得有问题,那两个button在建立的时候,引用计数就为1(这个是系统自动释放),你alloc了,引用计数+1,release之后,引用计数为1,在removeFromSuperview时候,内存就没了,而且你的btn1与btn2都在self.view上,删除就全部释放了,第二次输出的时候,btn1都没有了,当然奔溃了。
    还有在建立button的时候,应该是self.btn1吧,这样能防止能存泄露。
      

  3.   

    苹果的文档有提到,永远不要用 retainCount 这个方法,
    应为它不能正确的反映对象的 retain count. 
    当你 release 一个对象时,他的retain count 不会马上变化,而只是发送 release 这个消息, 
    当没有任何方法引用这个对象时才会变。 
      

  4.   


    我在button1中建立控件,在 button2中删除控件,这只是用来看下retainCount的代码。没必要调用viewDidLoad吧。
    代码里的问题是:在View上两个控件,retainCount都为2,我把btn1   release了,结果btn2的retainCount也变了。
      

  5.   


    我在button1中建立控件,在 button2中删除控件,这只是用来看下retainCount的代码。没必要调用viewDidLoad吧。
    代码里的问题是:在View上两个控件,retainCount都为2,我把btn1   release了,结果btn2的retainCount也变了。

    理论上讲,你的问题应该不会存在,我还是建议你子类化一个Button,只对btn2子类化也可以,看下btn2什么时候调用的release
      

  6.   


    我在button1中建立控件,在 button2中删除控件,这只是用来看下retainCount的代码。没必要调用viewDidLoad吧。
    代码里的问题是:在View上两个控件,retainCount都为2,我把btn1   release了,结果btn2的retainCount也变了。
    我看你这个是storyBoard,这里面release不报错误么,我一般都是手敲代码,近期才用storyboard的,release 是报错误的。
    我纠正我以上说的一点,在ARC中,你的那个点击事件不用调用就可以,这是ARC的好处,我以前是用MRC的。
      

  7.   


    我在button1中建立控件,在 button2中删除控件,这只是用来看下retainCount的代码。没必要调用viewDidLoad吧。
    代码里的问题是:在View上两个控件,retainCount都为2,我把btn1   release了,结果btn2的retainCount也变了。
    我看你这个是storyBoard,这里面release不报错误么,我一般都是手敲代码,近期才用storyboard的,release 是报错误的。
    我纠正我以上说的一点,在ARC中,你的那个点击事件不用调用就可以,这是ARC的好处,我以前是用MRC的。没用arc.本来是用了的,但内存长得太吓人。只要手工维护,取消了arc.然后就发现,在一个view上两控件,把第一个删了,竟然第二个控件的retainCount也会变。但如果有三个控件,删第一个时,retaincount会变,删第二个时,就不再变了。直接就晕了看资料上也没这说法啊
      

  8.   

    还有更怪的。一个control的view上,再加个view为基类的类,然后在这个类中dealloc中看类中变量的retainCount,为1,release后,正常。然后在一个线程中触发到了这个dealloc,各种crash,那么在变量赋值时retain一下,可以了。但线程和非线程调用时总有一个retainCount不是想要的数目
      

  9.   

    试了下,效果是和你的一样。原本按我的理解,这样的执行过程,btn1在被移除父视图时候,应该就会被释放,但是接下来调用了
    [btn1 removeFromSuperview];
        NSLog(@"111:%d",[btn1 retainCount]);//////输出为:1     它变为1 理解     暂可读取
    这里本来应该崩溃的,可是没有。然后我再建了一个方法,把你在- (IBAction)button222:(id)sender 中得代码拆成了两部分,就是把[btn1 removeFromSuperview];之后放到另一个方法里面来,- (IBAction)button222:(id)sender保留上半部分:
    - (IBAction)tap3:(id)sender {
        NSLog(@"111:%d",[btn1 retainCount]);//////输出为:1     它变为1 理解     暂可读取
        NSLog(@"222:%d",[btn2 retainCount]);//////输出为:1     它为什么也变为1?????
        
        [btn2 removeFromSuperview];
        
        NSLog(@"222:%d",[btn2 retainCount]);//输出为:1  暂可读取
        NSLog(@"111:%d",[btn1 retainCount]);//泄漏
    }
       这是执行了两个方法,在执行这一个就会在NSLog(@"111:%d",[btn1 retainCount]);这里就崩溃。也就是说在btn1移除之后,隔了一点时间才调用btn1,然后会崩溃。我的理解是,当引用计数为0之后,这个内存不会立即释放掉,有一个短暂的时间间隔,所以在btn1移除之后马上继续使用它,输出来引用计数还是1。
        而且如果把NSLog(@"111:%d",[btn1 retainCount])注释掉,会可以继续执行,这时NSLog(@"222:%d",[btn2 retainCount]);输出来的结果就是2了。所以btn2的引用计数应该是受其btn1的引用计数影响的,但短暂的时间后,btn2的引用计数又会回到正常。我不知道这是什么原因,不过引用计数也是要计算的,系统方法也要时间,我这么想的。
      

  10.   

    还有一个问题:NSLog(@"111:%d",[btn1 retainCount]);//////输出为:1     它变为1 理解     暂可读取。这里输出为1是错的,对于UIView的继承类,从父视图移除,引用计数是减掉2的(addSubView是增加2)。btn1开始被构建的时候是1,addsubView之后是3,然后又被release才会变成2。
      

  11.   


    我在button1中建立控件,在 button2中删除控件,这只是用来看下retainCount的代码。没必要调用viewDidLoad吧。
    代码里的问题是:在View上两个控件,retainCount都为2,我把btn1   release了,结果btn2的retainCount也变了。
    我看你这个是storyBoard,这里面release不报错误么,我一般都是手敲代码,近期才用storyboard的,release 是报错误的。
    我纠正我以上说的一点,在ARC中,你的那个点击事件不用调用就可以,这是ARC的好处,我以前是用MRC的。没用arc.本来是用了的,但内存长得太吓人。只要手工维护,取消了arc.然后就发现,在一个view上两控件,把第一个删了,竟然第二个控件的retainCount也会变。但如果有三个控件,删第一个时,retaincount会变,删第二个时,就不再变了。直接就晕了看资料上也没这说法啊在ARC中,不用自己管理内存的,MRC中才是自己手动管理内存,如果一个项目中,出现ARC和MRC,会出现很多 crash的,即使你没发现,有时候也会奔溃,放在一起,内存有时候就弄混了,建议编程还是用一种模式就好,两种不适合。