ios开发-内存管理-理解

retaincount是引用计数的意思。

使用release使retaincount-1,使用retain使retaincount+1,当retaincount等于0的时候,该对象会被释放掉。

非ARC内存管理:

(1)如果调用了alloc\new\copy产生了一个新对象,最后肯定要调用一次release或者autorelease。

(2)如果让一个对象做了retain操作(计数器+1),最后肯定要调用一次release或者autorelease。

(3)内存管理原则是有加有减。

在内存管理时会碰到下面的几个问题:

(1)野指针

可将对象赋值为nil,可以避免野指针的出现。

[p release]; 

p = nil; 

p.age = 30;//相当于 [nil setage:30],这样就不会造成野指针,如果不加第二行代码,会造成野指针。

(2)内存泄露

不被使用的对象,一直在内存中没有被销毁。会造成内存泄露

[p retain];  //retaincount=2

[p retain];  //retaincount=3

[p release]; //retaincount=2

上面三行代码代码会导致内存泄露,因为p对象没有完全释放,他的retaincount不等于零。

p = nil;

[p release];   //此行代码相当于[nil release],但是他并没有让retaincount 进行-1的操作

(3)set方法的内存管理写法

-  (void) setCar: (Car *) car

{

if ( _Car != car)

{

[_Car release];

_Car = [Car retain];

}

}


接下来是autoreleasepool,也就是自动释放池:

对象存入到自动释放池中,当这个池子被销毁时,会对池中的对象进行一次release操作,

在一个项目中会有一个默认的autoreleasepool,在项目文件main.m里面,实际上他是一个死循环。一直到程序终止才被销毁。

int main(int argc,char * argv[]) {

    @autoreleasepool {

        returnUIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegateclass]));

    }

}


需要注意的是:

 (1) 只有在autoreleasepool作用域中,调用autorelease方法,才能将对象添加到自动释放池中。

   @autoreleasepool {

        Car *c = [ [ [ Car alloc ] init ] autorelease ];

    }

(2)函数返回值,不能直接用release,如果直接用release可能会造成野指针的错误,这时候可以选择使用autorelease。

(3)系统对象本身都是autorelease,不能用对齐使用release。例如不能 : NSString *str = @"str";[str release];


接下来是集合手动管理内存的方法:

(1)当对象添加进数组的时候,会retain一次。

[array addobject:p];

(2)当对象删除的时候,会release一次。

[arrat removeobject:p]

(3)当数组release的时候,会release一次。


block的内存管理:

block内存管理默认是在栈中,开发人员不需要去管理block内存

Dog *d = [[Dog alloc]init];

        void (^Myblock)() = ^

        {

            NSLog(@"%@",d.age);

        };

        

        Myblock();

        

        Block_copy(Myblock);

        

        //Block_release(Myblock);

在上面的Block_copy(Myblock)这一句,对block进行了copy操作 ,block的内存会搬到堆里面,Dog的retainCount会加1,

Block_release(Myblock)这一句虽然会把block进行一次release操作,但是Dog的retainCount仍然是2.

在这里可以通过[ d  retainCount]查看Dog的retainCount到底有多少。

为了解决这个问题,在非ARC情况下,可以在定义Dog的时候,加上__block,在ARC情况下,可以加上__weak或者__unsafe_unretained解决这个问题。

__block Dog *d = [[Dog alloc]init];

__weak Dog *d = [[Dog alloc]init];

__unsafe_unretained Dog *d = [[Dog alloc]init];

还有就是如果一个对象拥有一个block,是不能用assign参数,因为这样block在栈里面,不能确保block会存在,只能用copy,这样就把block放到堆里面,

需要注意的是如果此时实在非ARC情况下,需要在dealloc方法里面,使用Block_release(Myblock)进行一次release操作。


除此之外是集合在ARC下的内存分析:

(1)当一个对象被存入集合的时候,默认是保存强指针

(2)array = nil;//数组被销毁

(3)[array removeobject:p]; --------> p=nil; ------------>p被销毁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值