使用@property配合@synthesize可以让编译器自动实现getter/setter方法,使用的时候也很方便,可以直接使用“对象.属性”的方法调用。而其中的assign,copy和retain三个属性及点语法在oc内存管理中起着至关重要的作用。在此仅对retain属性的实际语法代码极其原理经行剖析。
retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1对其他NSObject和其子类
对参数进行release旧值,再retain新值
对参数进行release旧值,再retain新值 指定retain会在赋值时唤醒传入值的retain消息。此属性只能用于Objective-C对象类型,而不能用于Core Foundation对象。(原因很明显,retain会增加对象的引用计数,而基本数据类型或者Core Foundation对象都没有引用计数——译者注)。
注意: 把对象添加到数组中时,引用计数将增加对象的引用次数+1。
retain的实际语法为:
- (void)setName:(NSString *)name {
if (_name != name) {
[_name release];
_ name = [name retain];
}
}
现在就让我们用下面浅显的代码来剖析下retain的实际语法原理
在main.h中
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Class_16.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Person *person1=[[Person alloc] init];//对象由alloc申请空间,引用指数加1,此时为1
Class_16 *class_16=[[Class_16 alloc] init];//同上
class_16.person=person1;//调用Class_16.m的setPerson方法 引用指数加1,此时为2
[person1 release];//person1对象release后,person1对象的引用指数减1,变为1(注:此时的person1对象的引用指数是1,占用的内存空间还未被释放)
[class_16.person eat];//eat方法用来作测验
Person *person2=[[Person alloc] init];//对象由alloc申请空间,引用指数加1,此时为1
class_16.person=person2;//class_16.person重指向person2,此时调用Class_16.m的setPerson方法此时person2引用指数
//加1,此时为2(而经过setPerson中的 [_person release];语句,使得person1指向的对象引用指数-1,变为1.从而person1指向的对象占用的空间得以释放)
[person2 release];//person1对象release后,person1对象的引用指数减1,变为1
[class_16.person eat];//eat方法用来作测验
[class_16 release]; //自动调用Class_16.m中的dealloc方法,即person2对象release,person1对象的引用指数减1,变为0,person2占用的内存被释放
}
return 0;
}
下面的getter方法中的判断条件
(_person!=person)的作用是当 Class_16 *class_16重指向的对象相同时,避免无谓的重复操作。
- (void)setPerson:(Person *)person
{
if (_person!=person) {
[_person release];
NSLog(@"%lu",[_person retainCount]);
NSLog(@"%lu",[person retainCount]);
_person=[person retain];
NSLog(@"%lu",[_person retainCount]);
}
}
====================================================
Person类的.h文件#import<Foundation/Foundation.h>
@interface Person :NSObject
@property (nonatomic,retain)NSString *name,*type;
- (id)initWithName:(NSString *)name andType:(NSString *)type;
+ (id)personWithName:(NSString *)name andType:(NSString *)type;
-(void)eat;
@end
person类的.m文件
#import "Person.h"
@implementation Person
@synthesize name=_name,type=_type;
- (void)setName:(NSString *)name
{
}
- (void)dealloc
{
NSLog(@"person dealloc");
[self.namerelease];
[self.typerelease];
[super dealloc];
}
- (id)initWithName:(NSString *)name andType:(NSString *)type
{
self=[superinit];
if (self) {
self.name=name;
self.type=type;
}
returnself;
}
+ (id)personWithName:(NSString *)name andType:(NSString *)type
{
Person *person=[[Personalloc]initWithName:nameandType:type];
[person autorelease];//在某一适当时间释放
return person;
}
-(void)eat
{
NSLog(@"吃");
}
@end
====================================================
Class_16类的.h文件
#import <Foundation/Foundation.h>
#import "Person.h"
@interface Class_16 :NSObject
@property (nonatomic,assign)Person *person;
- (id)initWithName:(Person *)person;
+ (id)class_16WithName:(Person *)person;
@end
Class_16类的.m文件
#import "Class_16.h"
#import "Person.h"
@implementation Class_16
- (void)dealloc
{
NSLog(@"person dealloc");
[self.personrelease];
[super dealloc];
}
- (void)setPerson:(Person *)person
{
if (_person!=person) {
[_personrelease];
NSLog(@"%lu",[_personretainCount]);
NSLog(@"%lu",[personretainCount]);
_person=[personretain];
NSLog(@"%lu",[_personretainCount]);
}
}
- (id)initWithName:(Person *)person
{
returnnil;
}
+ (id)class_16WithName:(Person *)person
{
returnnil;
}
@end
====================================================