刘 one punch的iOS开发日记 OC篇( 内存管理篇 )

  由于内存管理部分较难理解,所以记录在此以备不时之需,如有错误和不足欢迎大家指正。
  手动内存管理(MRC)部分:
  1.引用计数:生成一个对象的时候,将对象的引用计数记为1,每调用该对象一次引用计数就加一,不使用时便减一,只到引用计数为0并释放。
  2.当对象使用[p retain],[p alloc],[p new],copy,Mutablecopy方法时,均可以使retainCount加一。
    当对象使用[p release]时,引用计数减一,[p retainCount]可以查看引用计数。
  3.内存管理错误的几种类型:
      1.内存泄漏:对象在不使用时未释放
      2.野指针:对象提前释放
      3.僵尸对象:执行过度释放方法
  4.dealloc方法的使用:- (void)dealloc {self.dog = nil; [super dealloc];}
    该方法为引用计数为0时系统自动调用,不能手动调用  (具体实例下面会给出)
  5.关于对象所有权的问题:
      1.定义:如果一个对象内有指向其他对象的实例变量,则称该对象拥有这些对象。
      2.内存管理法则:谁申请,谁释放。
      3.正因为在多个实体中对象所有权关系复杂,所以要保留引用计数大于一。
        举例:在Car类中有- (void)setWheel:(Wheel *)newWheel;
        在main函数中调用该方法:Wheel * wheel = [[Wheel alloc] init];
                            [car setWheel:wheel];
        现在就出现了问题:如果wheel对象属于main函数,但Car类正在使用它,
        可如果属于Car类,又不敢保证之后main函数不会再使用这个对象。
        解决方法如下:让Car类保留wheel对象,并使引用计数器的值为2,
        这是因为main函数和Car类都在使用wheel这个对象,Car类应该
        在setWheel方法保留这个对象,main函数负责释放这一对象,当
        Car类完成其功能时再通过系统调用dealloc方法进行释放该对象。
  6.访问set方法中的保留与释放写法:
      1.如果我在set方法里写 wheel = [newWheel retain];则在main函数中
        以 Wheel *wheel1 = [Wheel new];  [car setWheel:wheel1];
        [wheel1 release];   会出现内存泄漏的错误,因为此时wheel的引用
        计数仍然为1,main函数释放了wheel1而Car类并未释放。
      2.如果我在set方法里写 [wheel release]; wheel = [newWheel retain];
        则在main函数中以 Wheel *wheel = [Wheel new]; Car *car1 =
        [Car new]; Car *car2 = [Car new]; [car1 setWheel: wheel];
        [wheel release]; [car2 setWheel: [car1 wheel]];  由于newWheel
        和wheel均指向刚释放的内存区,以至会引发错误。
      3.正确的写法之一:在set方法里写:[newWheel retain]; [wheel release];
        wheel = newWheel;  这样写的原因是首先保留新的wheel对象,就算两者是
        同一对象引用计数也会先加一,然后立即释放掉,再把newWheel赋给wheel,
        在set方法中先保留新对象,再释放对象就不会出现错误。

猜你喜欢

转载自liuonepunch.iteye.com/blog/2407681