非ARC下的开发-----retain、assign的使用详解
来源:互联网 发布:人工智能人才缺口 编辑:程序博客网 时间:2024/05/17 02:55
非ARC的内存管理原则
1、如果调用allock/new/copy产生一个新对象时必须要有调用一次release或autorelease
2、如果让一个对象进行了一次retain操作,最后肯定要调用一次release或autorelease操作
3、原则是计数器有加就有有减
assign一般用于简单的数据类型(如如NSInteger,double,bool)、代理等,retain一般用于对象
下面是通过代码进行一步步分析
问题代码一
Person.h文件
#import <Foundation/Foundation.h>@class Dog;@interface Person : NSObject{ Dog *_dog;};- (void)setDog:(Dog *)dog;- (Dog *)dog;@end
Person.m文件
#import "Person.h"#import "Dog.h"@implementation Person- (void)setDog:(Dog *)dog{ _dog = dog;}- (Dog *)dog{ return _dog;}@end
以上的代码相当于@property(assign ,nonatomic)Dog *dog;
main.m文件
int main(int argc, char * argv[]) { @autoreleasepool { Person *person = [[Person alloc]init];//1 Dog *dog1 = [[Dog alloc]init];//1 person.dog = dog1;// [dog1 release];//dog1:0 NSLog(@"%@",person.dog); [person release]; }}
在打印前dog1已经释放,此时,_dog变成了僵尸指针。结果显示消息发送给了一个释放的对象![](http://img.blog.csdn.net/20160630212507264)Xcode开启僵尸模式的方法:在Xcode的scheme页面中设置NSZombieEnabled环境变量。点击Product——>Edit Scheme打开该页面,然后勾选Enable Zombie Objects 复选框。
修改后的代码一(依然有问题)
#import "Person.h"#import "Dog.h"@implementation Person- (void)setDog:(Dog *)dog{ _dog = [dog retain];}- (void)dealloc{ [self.dog release]; [super dealloc];}- (Dog *)dog{ return _dog;}@end
修改了Person.m文件内容,修复了代码一中的问题
存在的问题
main.m文件
int main(int argc, char * argv[]) { @autoreleasepool { Person *person = [[Person alloc]init];//1 Dog *dog1 = [[Dog alloc]init];//1 Dog *dog2 = [[Dog alloc]init]; person.dog = dog1;//dog1:2 person.dog = dog2;//dog2:2 [dog1 release];//dog1:1 [dog2 release];//dog2:1 [person release];//person:0 dog2:0 }}
修改Persom.m的代码
- (void)setDog:(Dog *)dog{ [_dog release]; _dog = [dog retain];}
在retain新值前先把旧值release掉
运行结果:
该代码依然有问题
main.m文件代码
int main(int argc, char * argv[]) { @autoreleasepool { Person *person = [[Person alloc]init];//1 Dog *dog1 = [[Dog alloc]init];//1 person.dog = dog1;//dog1:2 [dog1 release];//dog1:1 person.dog = dog1;//dog1:0 [person release];//person:0 }}
第一次person.dog = dog1前person.dog =nil,release旧值相当于[nil release],dog1的计数器不变还是1,又进行了一次retain操作,所以dog1的计数器是2
第二次person.dog = dog1之前有一次release操作,dog1计数器变为1。此时,再person.dog = dog1时因为person.dog有旧值,先进行release操作,dog1计数器此时为为0,dog1被释放。再进行retain操作就会有野指针错误。
修改后的正确的代码
- (void)setDog:(Dog *)dog{ if (_dog!=dog) { [_dog release]; _dog = [dog retain]; }}
此时的代码相当于@property(retain ,nonatomic)Dog *dog;
比较严谨的写法还要修改-(void)dealloc方法
- (void)dealloc{ [_dog release]; _dog = nil; [super dealloc];}
或者
- (void)dealloc{ self.dog = nil; [super dealloc];}
注意iOS版本是5.0或4.3时在控制器使用retain关键字的属性时还要添加以下代码
- (void)viewDidUnload{ [super viewDidUnload]; self.dog = nil;}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; self.dog = nil;}
- 非ARC下的开发-----retain、assign的使用详解
- iOS开发之ARC下的代理weak VS assign
- IOS开发中ARC下的assign和weak区别
- iOS开发中ARC下的assign和weak区别
- IOS开发中ARC下的assign和weak区别
- iOS开发--assign、retain、copy的区别
- 在ARC下 选择使用weak和assign的区别
- retain 和 assign 的区别使用
- iOS ARC下的cycle retain
- iOS Block在ARC/非ARC下的使用总结
- iOS Block在ARC/非ARC下的使用总结
- ARC 下使用非ARC的.m文件
- iOS Block在ARC/非ARC下的使用总结
- ARC和非ARC下使用Block属性的问题
- ARC和非ARC下使用Block属性的问题
- block在ARC/非ARC下的使用
- ARC下的assign和weak区别
- readwrite, readonly, assign, retain, copy, nonatomic属性的作用? 什么情况使用copy,assign和retain?
- Linux CPUFreq
- leetcode-java-101. Symmetric Tree
- 深入理解CSS溢出overflow
- microsoft Sourcesafe 客户端使用
- Half精度解析
- 非ARC下的开发-----retain、assign的使用详解
- June's English Summary
- 设置Myeclipse中的代码格式化、注释模板及保存时自动格式化
- 224.leetcode Basic Calculator(hard)[后缀表达式 栈]
- 一起talk C栗子吧(第一百六十九回:C语言实例--再谈内置宏)
- django学习笔记1:安装
- shiro+spring相关配置
- 大三的最近感悟
- 第三天 程序控制流程、选择分支结构、循环结构