本节目录
retain
先建一个student类,和一个Book类,学生拥有有一本书
Book.m
#import "Book.h" @implementation Book -(void)dealloc{ NSLog(@"Book 被销毁"); [super dealloc]; } @end
Student.h,nonatomic先不理,后面来讲
#import <Foundation/Foundation.h> #import "Book.h" @interface Student : NSObject @property(nonatomic,retain)Book *book; @end
int main(int argc, const char * argv[]) { @autoreleasepool { Student *stu = [[Student alloc] init]; Book *book = [[Book alloc] init]; stu.book = book; //打印的结果变成2,说明,retain声明的属性的引用计数器为+1 NSLog(@"book returnCount: %lu",[book retainCount]); [book release]; [stu release]; } return 0; }
打印的结果变成2,好,那我们看下有retain的set方法是怎么做的
#import "Student.h" @implementation Student -(void)setBook:(Book *)book{ //如果传进的book对像跟已经持有book对象不相等,这时我们就替换原有的book对象为传进来的book对象 if (_book != book) { //先release以前的book对象,释放内存 [_book release]; //return下,持有book对象 _book = [book retain]; } } @end
总结:retain会使引用计数器加1,谁持有对象,就要对对象进行释放操作
上面的代码还有问,我们还应该在Student的dealloc方法进行book的释放操作,永远记住,谁持有对象,就要对它负责
#import "Student.h" @implementation Student -(void)setBook:(Book *)book{ //如果传进的book对像跟已经持有book对象不相等,这时我们就替换原有的book对象为传进来的book对象 if (_book != book) { //先release以前的book对象,释放内存 [_book release]; //return下,持有book对象 _book = [book retain]; } } -(void)dealloc{ [_book release]; [super dealloc]; } @end
这样在执行main方法时,Book的dealloc方法才会被调用,才证明book已经被释放了。
结果
2014-03-17 18:01:25.827 HellowWord_OC[2243:303] book returnCount: 2 2014-03-17 18:01:25.829 HellowWord_OC[2243:303] Book 被销毁
assign
把student持有的book的retain属性变成assign,去掉student.m的set方法,运行main函数发现book被释放了。
这说明assign标识的属性没有把引用计数器加1,而是直接赋值,等效于下面
-(void)setBook:(Book *)book{ //如果传进的book对像跟已经持有book对象不相等,这时我们就替换原有的book对象为传进来的book对象 if (_book != book) { _book = book; } }
copy
#import <Foundation/Foundation.h> #import "Book.h" #import "Student.h" int main(int argc, const char * argv[]) { @autoreleasepool { Book *book = [[Book alloc] init]; NSMutableArray *array1 = [NSMutableArray arrayWithObjects:book, nil]; NSMutableArray *array2 = [array1 copy]; NSMutableArray *array3 = [array1 retain]; NSLog(@"array1 %p",array1); NSLog(@"array2 %p",array2); NSLog(@"array3 %p",array3); [array2 release]; [array3 release]; [book release]; } return 0; }
结果
2014-03-17 19:02:52.118 HellowWord_OC[2681:303] array1 0x10010be50
2014-03-17 19:02:52.120 HellowWord_OC[2681:303] array2 0x10010a9f0
2014-03-17 19:02:52.121 HellowWord_OC[2681:303] array3 0x10010be50
2014-03-17 19:02:52.121 HellowWord_OC[2681:303] Book 被销毁
看到array1和array2两个的地址空间不一样,array1和array3内存地址一样,copy会开辟一个新的内存空间来存放传进来的数据,并且引用计数器为1
也就是说, copy 是内容拷贝, retain 是指针拷贝。
什么时候用assign,什么时候用retain
int float long,char,BOOL等基本数据类型用assign,因为基本数据类型没有引用计数器的概念
NSString用copy.
其余的暂时用retain,到后面我们再在ios开发中哪些用assign