Objective-C的property理解

前面说到了内存管理,现在来说一下OC的一些高级语法。当然这些语法中还会涉及内存中的管理。

1、property

如果学习过Java,就会知道我门定义成员变量时编译器会自动生成对应的setter和getter,我们称之为存取方法。在OC中也不例外,但是我门需要自己写,如果成员变量太多,需要写很多setter和getter。于是出现了关键字property,这个关键字可以自动帮我们声明成员变量还有setter和getter,于是在implementation中需要添加@synthesize关键字,就可以自动合成存取方法。

以前的写法:

//.h
@interface MyClass : NSObject
{
    NSString* name_;
}
-(void)setName:(NSString*)name;
-(NSString*)name;
@end
//.m
@implementation MyClass

-(void)setName:(NSString*)name//setter方法
{
    name_ = name;
}
-(NSString*)name//get方法
{
    return name_;
}
@end

简要说明setter和getter的命名规则,虽然这不是重要的:
setter的命名规则:set+成员成员变量名称,名称首字母大写
getter的命名规则:成员变量名称
注意:如果成员变量又下划线等符号,在写存取方法的名称时,要忽略这些符号
下面是有property的写法:

//.h
@interface MyClass : NSObject
@property NSString* _name;
@end
//.m
@implementation MyClass
@synthesize _name;
@end

因此后续的{}成员变量列表就可以舍弃了。上述的写法是Xcode4.4以前的写法,现在只需要写@property。

//.h
@interface MyClass : NSObject
@property NSString* _name;
@end
//.m
@implementation MyClass
@synthesize _name;
@end

然后就会完成下面两件事情

  1. 自动生成私有成员变量
  2. 自动生成存取方法

有了上面的存取方法,就有了点语法,这个和C语言中访问struct的成员是一样的。

		MyClass* myclass = [MyClass new];
        myclass.name = @"hello";//这是settter方法
        NSLog(@"%@",myclass.name);//这是getter方法
2、属性特质

使用属性时,属性还有自己特质,这些特质胡影响编译器所生成的存取方法,属性的特质有如下四种:
原子性、读写权限、内存管理语义、方法名设置
下面分开来说

2.1 原子性

默认情况下,编译器合成的方法都护保证其原子性,所谓原子性就是在用set方法和get方法时是不可打断的——关键字atomic
但是原子性很影响效率。因此通常都是采用nonatomic。
网上有个面试题说:aotomic一定保证线程安全吗?
谈谈我的看法:我认为这个问题要从两个角度来考虑,一个是从setter和getter本身,一个是线程。对于setter和getter,如果是atomic特性,那么一定是线程安全的,也就是说该方法只能有一个线程进入,设置或者读取成员变量的数据。但是从对象的线程安全来说,并不是,类似下面的表达式。

self.xxx = self.xxx + self.xxx;
self.xxx = xxx;

atomic只能保证setter和getter的方法是原子性的,但一旦有了表达式等,就会有安全性问题。

2.2 读写权限

readonly和readwrite关键字

  1. readonly只读,在生成存取方法时,只会生成getter方法,用来获取属性的值。
  2. readwrite读写,一般属性的默认特质就是读写
2.3 内存管理语义
  1. assign:这个特质主要用起若引用的作用,引用之后不增加引用计数,如果引用对象被销毁,带有assign特质的属性值不会被置空。
  2. retain:强引用,引用对象时,会增加对象的引用计数。
  3. unsafe_unretain:和assign的作用相同,但是仅用于对象类型。
  4. weak:和assign作用相同,但是其在对象被销毁时,带有weak特质的属性会被置空。在当前ARC模式下,都会使用安全的weak。
  5. strong:类似于retain,当前ARC模式下使用。其与retain的区别,将在后续学习block时会进行回顾与记录。
  6. copy:在C++中,我们称之为深拷贝。不是直接强引用一个对象,而是直接拷贝资源。用@property声明 NSString、NSArray、NSDictionary 经常使用copy关键字。

注意strong与copy的区别,一个是直接引用对象,一个是拷贝。教材与网上的资料说strong是“保留新值,释放旧值,填充新值”,copy是“不保留新值,将其拷贝”。看着可能有些迷糊。其实就是带strong特性的属性在赋值的时候,会先将原来的对象的引用计数-1,然后强引用赋值的对象。而copy是直接copy,自己拥有一个对象,与赋值的对象不是同一个对象和资源。如下代码进行说明:

首先在怪兽类中声明两个不同特质的属性:

@interface Monster : NSObject
@property(copy, nonatomic) NSString* strings_;//copy
@property(strong, nonatomic) NSString* stringp_;//strong

-(void)Print;
@end

实现的内容就忽略了,

        Monster* m1 = [[Monster alloc] init];
        //首先进行两个属性的赋值
        m1.strings_ = @"哥尔赞";
        m1.stringp_ = @"美尔巴";
		//打印一下两个属性
        [m1 Print];

		//创建一个可变字符串对象
        NSMutableString* str = [NSMutableString  stringWithFormat:@"伽库玛"];;
		//进行赋值
        m1.strings_ = str;
        m1.stringp_ = str;
		//打印属性
        [m1 Print];
		//现在改变str这个对象的值
        [str appendString:@"基里埃洛德"];
        //打印
        [m1 Print];

在这里插入图片描述

2.4 方法名设置

这个简单就是:
getter=,setter=,改变原来setName或者getter这种命名格式格式
可以这样:

@property(copy, nonatomic, setter=<willBe>) NSString name;
3、属性与成员变量

一开始各种资料或者网上的博客都是成员变量、实例变量、属性搞不清楚,最后在分析对象内存分布的时候一头雾水。其实以property声明的方式,称之为属性,而在{}中声明的变量,为成员变量。
属性是私有的,而成员变量可以调整访问权限,但是通常都是私有的。
前面提到的种种,如自动生成存取方法都是属性拥有的,而成员变量需要自己去写存取方法。
属性声明时,编译器回自动帮助我们添加前缀下划线。属性和成员变量时两个不同的值。

@interface MyClass : NSObject
{
    //测试存取方法是否会忽略名称中的符号
    NSString* na_me_;//成员变量
}
@property(copy, nonatomic) NSString* member;//属性,(即使自己写了下划线编译器还是会再添加一个下划线)

-(void)setName:(NSString*)name;//setter方法
-(NSString*)name;//getter方法
@end

在这里插入图片描述
折腾出真知,当前的属性介绍完毕。下一站——协议

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值