您的位置:首页 > 编程语言

oc内存管理中retain属性对应的setter实际语法代码实现及原理

2014-02-13 21:43 417 查看
使用@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

====================================================
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: