从GetSet看iOS内存机制 (一)

在ARC下理解@property和@synthesize机制:

情况一:成员变量  @property  @synthesize  同一个名字

@interface Person : NSObject
{
    
    @public
    NSString* birthday;
    
}

@property NSString* birthday;

@end

#import "Person.h"

@implementation Person

@synthesize birthday;

@end


#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "Person.h"

int main(int argc, char * argv[]) {
    @autoreleasepool {
        
        Person* p = [[Person alloc] init];
        
        p-> birthday = @"1987-08-20";<span style="white-space:pre">		</span>//赋值成员变量
        p.birthday = @"1986-08-08";<span style="white-space:pre">		</span>//赋值点取的birthday<span style="white-space:pre">	</span>
        NSLog(@"p-> birthday :%@ --- %p", p->birthday, p->birthday);      //分别输出成员变量和点取的值和地址
        NSLog(@"p.birthday :%@ --- %p", p.birthday, p.birthday);
        
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}




结论:成员变量和@property同名且指定@synthesize时候,p-> variable和p.variable效果一样,指的是同一个变量。那为什么会指的是同一个变量呢,因为@synthesize birthday; 编译器会自动监测成员变量有没有同名的,如果有,则做操作:@synthesize birthday = birthday;(后者为成员变量的birthday)。这样属性和成员变量就为同一个变量。那么,假设成员变量没有birthday,只有@property和@synthesize有birthday会怎么样,请看情况五。 



情况二:在情况一的基础下将@synthesize去掉

这时候报了一个警告:


大意就是被自动生成的birthday变量将使用自动生成的实例变量_birthday,不存在实例变量birthday。

这时候的输出是:


很明显没有了@synthesize后,@property的birthday和成员变量的birthday完全不是一个变量,这个时候在Person类增加一个输出方法:

- (void)printInfo
{

    NSLog(@"_birthdat = %@", _birthday);
}

在看看结果如下:


很显然说明结果:如果不使用@synthesize,编译器默认自动生成属性birthday为:_birthday即加下划线,其实很多好处,最大好处的防止方法同名(getset中)。这个时候生成的下划线_birthday和成员变量birthday没有任何关系哦



情况三:情况二的一种特例,如果成员变量声明的恰好的是下划线_sex,@property sex,没有@synthesize那会怎么样呢?

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    
    @public
    NSString* _sex;
}

@property NSString* sex;

- (void)printInfo;

@end

#import "Person.h"

@implementation Person

- (void)printInfo
{
    NSLog(@"_sex = %@", _sex);
    NSLog(@"self.sex = %@", self.sex);
}

@end

#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "Person.h"

int main(int argc, char * argv[]) {
    @autoreleasepool {
        
        Person* p = [[Person alloc] init];

        p->_sex = @"female";
        NSLog(@"p->_sex = %@ --- %p", p->_sex, p->_sex);
        NSLog(@"p.sex = %@ --- %p", p.sex, p.sex);
        
        p.sex = @"male";
        NSLog(@"p->_sex = %@ --- %p", p->_sex, p->_sex);
        NSLog(@"p.sex = %@ --- %p", p.sex, p.sex);
        
        NSLog(@"---------------");
        
        [p printInfo];
        
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}


结果:如有只有@property sex而没有@synthesize的话,就会自动生成一个_sex变量,如果恰好有成员变量_sex,这个时候他们是同一个变量,和情况二相比编译器并没有报警告为难你哦。




情况四:成员变量使用_position下划线,@property声明没有下划线变量position,@synthesize声明没有下划线变量position

@interface Person : NSObject
{
    
    @public
    NSString* _position;
    
}

@property NSString* position;

@end

#import "Person.h"

@implementation Person

@synthesize position; 

- (void)printInfo
{
    NSLog(@"position = %@", _positon);   
    NSLog(@"position = %@", position);
}

@end

int main(int argc, char * argv[]) {
    @autoreleasepool {
        
        Person* p = [[Person alloc] init];

        
        p-> _positon = @"developer";
        p.position = @"architect";
        NSLog(@"p->_position :%@ --- %p", p-> _positon, p-> _positon);
        NSLog(@"p.position :%@ --- %p", p.position, p.position);

        [p printInfo];
        
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}



结论:进一步验证了上面的结论@synthesize position; 相当于:@synthesize position = position;而不会自动生成下划线变量。



情况五:成员变量_degress,@property degress,@synthesize degress = _degress

@interface Person : NSObject
{
    
    @public
    NSString* _degress;
    
}

@property NSString* degress;

@end

#import "Person.h"

@implementation Person

@synthesize degress = _degress; 

- (void)printInfo
{
    NSLog(@"_degress = %@", _degress);   
    NSLog(@"degress = %@", degress);  ----- 报错,不能省
    //经修改后 <p class="p1"><span class="s1">    </span><span class="s2">NSLog</span><span class="s1">(</span><span class="s3">@"self.degress = %@"</span><span class="s1">, </span><span class="s4">self</span><span class="s1">.</span><span class="s2">degress</span><span class="s1">);</span></p>}

@end

int main(int argc, char * argv[]) {
    @autoreleasepool {
        
        Person* p = [[Person alloc] init];
        
        p.degress = @"undergraduate";
        NSLog(@"p->_degress :%@ --- %p", p->_degress, p->_degress);
        NSLog(@"p.degress :%@ --- %p", p.degress, p.degress);
        
        p->_degress = @"graduate";
        NSLog(@"p->_degress :%@ --- %p", p->_degress, p->_degress);
        NSLog(@"p.degress :%@ --- %p", p.degress, p.degress);
        
        NSLog(@"----------------------");

        [p printInfo];
        
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}


结论:通过@synthesize degress = _degress;相当于将属性degress指定别名_degress,这时候成员变量和属性为同一个变量,而且不能直接获取degress,进一步说明上面的结论。



情况六:成员变量中没有,@property中声明education,@synthesize声明education

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property NSString* education;

@end<span style="color:#cc33cc;">
</span>
#import "Person.h"

@implementation Person

@synthesize education;

- (void)printInfo
{
    NSLog(@"education = %@", self.education);
    NSLog(@"education = %@", education);
}

@end

#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "Person.h"

int main(int argc, char * argv[]) {
    @autoreleasepool {
        
        Person* p = [[Person alloc] init];

        p.education = @"scnu";
        
        [p printInfo];
        
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}



结论:如果成员变量没有education,只分别@property education和@synthesize education的话,不生成_education,其实和_position一样情况。只是相当于@synthesize education = education罢了,导致可以直接取。



情况七:成员变量和@synthesize中没有,只在@property中声明weight

@interface Person : NSObject

@property float weight;

- (void)printInfo;

@end
#import "Person.h"

@implementation Person

- (void)printInfo
{
    NSLog(@"_weight = %.2f", _weight);
    NSLog(@"self.weight = %.2f", self.weight);
    
}
@end

#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "Person.h"

int main(int argc, char * argv[]) {
    @autoreleasepool {
        
        Person* p = [[Person alloc] init];

        p.weight = 128.0;
        
        [p printInfo];
        
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

结论:这个是最常用的啦。如果没有做@synthesize的话,默认生成一个_weight,但是这种语法糖很有局限性,比如你只能在Person类中取得到,但是无法通过对象p取得到。


转自和总结:(http://www.cnblogs.com/kenshincui/p/3861302.html




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值