若类的某个字段为类对象,则在MRC条件下其存取器的 retain、copy、assign 设置至关重要。 下面是在网上查到的 retain、copy、assign 的工作方式说明:
assign:本参数的缺省值,不重新申请内存,也不给对象的引用计数加1,只是单纯的引用
retain:相当于多个变量指向同一个对象,使用引用计数;
copy: 复制一个新的过来,他们不再指向同一个对象:
下面代码是在MRC模式下运行,且不加NSAutoreleasePool池!
//下面代码实在MRC模式下运行的
#import <Foundation/Foundation.h>
@interface person:NSObject
{
NSString *name;
}
@property(copy) NSString *name;
+(instancetype) newPersonWithName: (NSString *) strName;
@end
@implementation person :NSObject
@synthesize name;
+(instancetype) newPersonWithName: (NSString *) strName
{
person* newSelf= [self new];
newSelf.name=strName;
return newSelf;
}
@end
int main(int argc,const char * argv[])
{
NSAutoreleasePool *pool=[NSAutoreleasePool new];
NSMutableString *mstr=[NSMutableString stringWithString:@"liji"];
printf("%lu\n",[mstr retainCount]); //retain 输出1 //assign 输出1 //copy 输出1
person *perX=[person newPersonWithName:mstr]; //调用了本类name属性的的Setter方法
printf("%lu\n",[mstr retainCount]); //retain 输出2 //assign 输出1 //copy 输出1
[mstr release];
printf("%lu\n",[mstr retainCount]); //retain 输出1 //assign 输出非常大的一个数,mstr内存已经被释放了 //copy 输出 输出非常大的一个数,mstr内存已经被释放了
NSLog(@"%@\n",perX.name);NSLog(@"%@\n",perX.name);NSLog(@"%@\n",perX.name); //调用3次本类name属性的的Getter方法
//可能是因为NSLog里并不知道使用对象的属性getter是哪种方式,因此也不敢随便release.
printf("%lu\n",[mstr retainCount]); //retain 输出4 //assign 上面一行已抛异常 //copy 抛异常了
[pool drain];
printf("%lu\n",[mstr retainCount]); //retain 输出非常大数,str已被释放 //assign 上面已抛异常 //copy 上面已抛异常
}
从上述代码可以看到 retain、assign、copy的工作方式的区别 。