iOS内存管理上

iOS内存管理

例子1——QQ堂游戏
①A玩家,建立房间1 ————————房间1的人数为1
②B玩家,加入房间1 ————————房间1的人数为2
③游戏结束,B玩家离开房间1 ———— 房间1的人数为1
④A玩家,也离开房间1 ——————— 房间1的人数为0
分析:当A玩家创建了房间1时,房间的人数变为1,随着玩家B的加入,房间的人数变为2
          当游戏结束,B玩家离开房间1,此时人数变为1,但是房间1还在
          最后当房间A离开房间1的时候,人数表位0,此时系统会将房间1释放
这就是内存管理的基本原则,通过对象内存计数器对对象所占用的内存进行管理,当有变量或者对象占用这块内存的时候,计数器加1,当某个变量或者对象不占占用时,计数器减1。当对象内存计数器变为0时,该对象释放。


例子2——人和书的关系
①创建书对象———————— 内存计数器加1 
②创建人对象———————— 内存计数器加1
③人可以拥有书———————书内存计数器加1
④人不再拥有书——————— 书内存计数器减1

注意
      Xcode默认会开启自动内存管理ARC机制(由iOS系统自动对内存进行管理),在学习内存管理中,我们需要将ARC管理机制关闭,否则,我们无法看到内存的管理的细节,诸如alloc \dealloc \release等方法无法重写

关闭方式
创建工程后,在Build Settings中搜索garbage,将ARC关闭即可,如下图:



接下来,我们进入代码的实现过程,看Objective-C是如何对内存进行管理的,仍然以人和书为例

/****************
1、创建Person类和Book类
2、分别创建对象
3、将Book对象赋给Person对象的_book属性
4、重写dealloc方法
5、观察对象的计数器变化
****************/

 
  1. #import <Foundation/Foundation.h>
  2.   @interface Book : NSObject
  3. {
  4. int _price;    //属性,价格
  5. }
  6. - (void)setPrice:(int)price;
  7. - (int)price;
  8. @end

  9. @implementation Book
  10. - (void)setPrice:(int)price
  11. {
  12. _price = price;
  13. }
  14. - (int)price
  15. {
  16. return _price;
  17. }
  18. @end


  19. @interface Person : NSObject
  20. {
  21. Book *_book;    //人拥有一本书
  22. }
  23. - (void)setBook:(Book *)book;
  24. - (Book *)book;
  25. @end

  26. @implementation Book
  27. - (void)setBook:(Book *)book
  28. {
  29. _book  = book;
  30. }
  31. - (Book *)book
  32. {
  33. return _book;
  34. }
  35. @end
  36. int main()
  37. {
  38. Book *b = [[Book alloc]init];
  39. Person *p =[[Person alloc]init];
  40. [p setBook:b];
  41. [p release];
  42. [b release];
  43. }



上述代码中,由于关闭了ARC自动内存管理机制,所以按照上述的写法,会产生内存泄露
分析如下:
首先,执行main函数后,在内存中的分布如下。



根据内存管理的原理,
执行第43行代码的时候,在内存中创建Book对象,此时Book对象内存计数器为1
执行第43行代码的时候,在内存中创建Person对象,此时Person对象内存计数器为1
当47行代码注释后,执行到48行代码时,Book对象的内存计数器减1变为0,此时Book对象被释放,此时p对象的_book属性仍然占用Book对象,会导致_book会出现内存泄露,所以需要进行内存管理


内存管理的原理是:谁占用,就需要对计数器加1(retain);解除占用后,需要对计数器减1(release)。
所以,上述代码中,需要做如下更改
①当执行45行代码的时,会调用Person对象的set方法,Book对象会被赋给_book属性,此时_book需要对Book对象计数器加1,所以setBook方法需要更改如下:
 - (void)setBook:(Book *)book
{
_book = [book retain];       //通过retain对计数器加1,且retain方法返回自身,所以仍然是将book赋值给_book.
}

②为了验证Book对象和Person对象是否被释放,我们分别在.m文件中(18行和38行后)重写dealloc方法
   注意,重写dealloc方法时,一定要在末尾调用[super dealloc]
   - (void)dealloc
   {
NSLog(@“Book对象被释放");
[super dealloc];
   }

  - (void)dealloc
  {
NSLog(@“Person对象被释放”);
[super dealloc];
  }

在重写了dealloc方法后,运行后的结果如下:

从运行结果中,我们可以看到,只有Person对象被释放,Book对象并未被释放。原因如下
当执行第45行代码的时候,调用了set方法,此时对Book进行了retain,计数器变为2。在48行的时候,计数器减1变为1,没有被销毁,没有调用dealloc方法。
所以,遵循内存管理原则(谁retain,谁release),Person对象需要解除对Book的占用,所以在Person对象被销毁之前,进行此项操作,故Person对象的dealloc方法需要被重写为如下:
  - (void)dealloc
  {
[_book release]; //对让Book对象的内存计数器减1
NSLog(@“Person对象被释放”);
[super dealloc];
  }

③通过上述更改,执行了47行和48行代码后,Book对象和Person对象被销毁。此时p和b指针指向了一块被释放的内存,如果再通过p和b操作该内存,会出现报错(野指针错误),所以需要分别在47行和48行后面分别加上如下代码:
p = nil;
        b = nil;
p和b被清空,空指针不会报错。





更改后的代码代码整体如下:

  1. #import <Foundation/Foundation.h>
  2.   @interface Book : NSObject
  3. {
  4. int _price;    //属性,价格
  5. }
  6. - (void)setPrice:(int)price;
  7. - (int)price;
  8. @end

  9. @implementation Book
  10. - (void)setPrice:(int)price
  11. {
  12. _price = price;
  13. }
  14. - (int)price
  15. {
  16. return _price;
  17. }
  18. - (void)dealloc
  19. {
  20. NSLog(@“Book对象被释放");
  21. [super dealloc];
  22. }
  23. @end


  24. @interface Person : NSObject
  25. {
  26. Book *_book;    //人拥有一本书
  27. }
  28. - (void)setBook:(Book *)book;
  29. - (Book *)book;
  30. @end

  31. @implementation Book
  32. - (void)setBook:(Book *)book
  33. {
  34. _book  = [book retain];    //Person对象占用书这个对象时,需要对计数器加1
  35. }
  36. - (Book *)book
  37. {
  38. return _book;
  39. }
  40. - (void)dealloc
  41. {
  42. [_book release];        //Book对象被释放
  43. NSLog(@“Person对象被释放”);     
  44. [super dealloc];
  45. }
  46. @end
  47. int main()
  48. {
  49. Book *b = [[Book alloc]init];
  50. Person *p =[[Person alloc]init];
  51. [p setBook:b];
  52. [p release];
  53. p = nil;
  54. [b release];
  55. p = nil;
  56. }





更多iOS开发相关资讯,欢迎关注“一路上有你”






























评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值