Objective-C语言--@property

来源:互联网 发布:网络爬虫 用什么语言 编辑:程序博客网 时间:2024/05/24 05:15

1.@property是什么

@Property是声明属性的语法,它可以快速方便的为实例变量创建存取器,并允许我们通过点语法使用存取器。

存取器(accessor):指用于获取和设置实例变量的方法。用于获取实例变量值的存取器是getter,用于设置实例变量值的存取器是setter。

2.创建存取器

2.1 手工创建存取器

我们先看两段代码:

// Car.h#import <foundation foundation.h="">@interface Car : NSObject{    // 实例变量    NSString *carName;    NSString *carType;}// setter                                   - (void)setCarName:(NSString *)newCarName; // getter- (NSString *)carName;// setter- (void)setCarType:(NSString *)newCarType;// getter- (NSString *)carType;@end</foundation>
上面的代码中carName和carType就是Car的实例变量,并且可以看到分别对这两个实例变量声明了get/set方法,即存取器。

#import "Car.h"@implementation Car// setter- (void)setCarName:(NSString *)newCarName{    carName = newCarName;}// getter- (NSString *)carName{    return carName;}// setter- (void)setCarType:(NSString *)newCarType{    carType = newCarType;}// getter- (NSString *)carType{    return carType;}@end

上面代码是对实例变量存取器的实现。我们可以看到,存取器就是对实例变量进行赋值和取值。按照约定赋值方法以set开头,取值方法以实例变量名命名。

我们看看如何使用:

// main.m#import "Car.h"int main(int argc, char * argv[]){    @autoreleasepool {        Car *car = [[Car alloc] init];        [car setCarName:@"Jeep Cherokee"];        [car setCarType:@"SUV"];        NSLog(@"The car name is %@ and the type is %@",[car carName],[car carType]);          }    return 0;}
上面的代码中我们注意到,对象Car使用了消息语法,也就是使用方括号的语法给存取器发送消息。 返回结果为:

The car name is Jeep Cherokee and the type is SUV


2.2 使用@Property创建存取器
// Car.h#import <foundation foundation.h="">@interface Car : NSObject{    // 实例变量    NSString *carName;    NSString *carType;}@property(nonatomic,strong) NSString *carName;@property(nonatomic,strong) NSString *carType;@end</foundation>
上面代码中,我们使用@property声明两个属性,名称与实例变量名称相同(让我们先忽略nonatomic和strong)。
// Car.m#import "Car.h"@implementation Car@synthesize carName;@synthesize carType;@end
在.m文件中我们使用@synthesize自动生成这两个实例变量的存取器,并且隐藏了存取器,虽然我们看不到存取器,但它们确实是存在的。

// main.mint main(int argc, char * argv[]){    @autoreleasepool {        Car *car = [[Car alloc] init];        car.carName = @"Jeep Compass";        car.carType = @"SUV";        NSLog(@"The car name is %@ and the type is %@",car.carName,car.carType);     }    return 0;}

在上面的代码中我们可以注意到,Car对象使用点语法给存取器发送消息,并且get与set的语法是相同的,所以这里的点语法可以根据语境判断我们是要赋值还是取值。当然我们也依然可以使用消息语法来使用:

// main.mint main(int argc, char * argv[]){    @autoreleasepool {        Car *car = [[Car alloc] init];        // 点语法//        car.carName = @"Jeep Compass";//        car.carType = @"SUV";//        NSLog(@"The car name is %@ and the type is %@",car.carName,car.carType);        // 消息语法        [car setCarName:@"Jeep Compass"];        [car setCarType:@"SUV"];        NSLog(@"The car name is %@ and the type is %@",[car carName],[car carType]);           }    return 0;}

上面两段代码的执行结果都是:

The car name is Jeep Compass and the type is SUV

总结:@property等同于在.h文件中声明实例变量的get/set方法,@synthesize等同于在.m文件中实现实例变量的get/set方法。使用@property和synthesize创建存取器要比手动声明两个存取方法(getter和setter)更简单。而且我们在使用属性时可以使用点语法赋值或取值,语法更简单,更符合面向对象编程。

3.不必单独声明示例变量

如果使用@Property,就不必单独声明实例变量了。因为在没有显示提供示例变量声明的前提下,系统会自动帮你生成实例变量。我们通过以下代码来说明:

// Car.h#import <foundation foundation.h="">@interface Car : NSObject@property(nonatomic,strong) NSString *carName;@property(nonatomic,strong) NSString *carType;- (NSString *)carInfo;@end</foundation>
在.h文件中我们并没有声明实例变量,只是声明了carName和carType两个属性,以及一个carInfo方法,返回值为NSString *。
// Car.m#import "Car.h"@implementation Car- (NSString *)carInfo{    return [NSString stringWithFormat:@"The car name is %@ and the type is %@",_carName,_carType];}@end

在.m文件中我们可以注意到,在carInfo方法中我们使用了_carName和_carType实例变量,这就是当我们没有显示声明实例变量时,系统为我们自动生成的。命名规则是以_为前缀,加上属性名,即_propertyName。

其实在.m文件中实际是存在@synthesize声明语句的,只是系统将其隐藏了:

@synthesize carName = _carName;@synthesize carType = _carType;

那么如果我们不喜欢默认的实例变量命名方法,或者我们希望使用更有语义的名称,应该怎么做呢。其实很简单:

// Car.m#import "Car.h"@implementation Car@synthesize carName = i_am_car_name;@synthesize carType = i_am_car_type;- (NSString *)carInfo{    return [NSString stringWithFormat:@"The car name is %@ and the type is %@",i_am_car_name,i_am_car_type];}@end

通过上述代码可以看到,我们只需要通过@synthesize来声明我们希望的实例变量名。

总结:如果我们希望使用默认的实例变量命名方式,那么我们在.m文件中就不需要使用@synthesize声明,系统会帮我们自动完成。如果我们希望自己命名实例变量命,那么我们就使用@synthesize显示声明我们希望的实例变量名。

4.@property的特性

@property还有一些关键字,它们都是有特殊作用的,比如上述代码中的nonatomic,strong:

@property(nonatomic,strong) NSString *carName;@property(nonatomic,strong) NSString *carType;

我把它们分为三类,分别是:原子性,存取器控制,内存管理。

4.1 原子性

atomic(默认):atomic意为操作是原子的,意味着只有一个线程访问实例变量。atomic是线程安全的,至少在当前的存取器上是安全的。它是一个默认的特性,但是很少使用,因为比较影响效率,这跟ARM平台和内部锁机制有关。

nonatomic:nonatomic跟atomic刚好相反。表示非原子的,可以被多个线程访问。它的效率比atomic快。但不能保证在多线程环境下的安全性,在单线程和明确只有一个线程访问的情况下广泛使用。

4.2 存取器控制

readwrite(默认):readwrite是默认值,表示该属性同时拥有setter和getter。

readonly: readonly表示只有getter没有setter。

有时候为了语意更明确可能需要自定义访问器的名字:

@property (nonatomic, setter = mySetter:,getter = myGetter ) NSString *name;
最常见的是BOOL类型,比如标识View是否隐藏的属性hidden。可以这样声明:

@property (nonatomic,getter = isHidden ) BOOL hidden;

4.3 内存管理

@property有显示的内存管理策略。这使得我们只需要看一眼@property声明就明白它会怎样对待传入的值。

assign(默认):assign用于值类型,如int、float、double和NSInteger,CGFloat等表示单纯的复制。还包括不存在所有权关系的对象,比如常见的delegate。

@property(nonatomic) int running;@property(nonatomic,assign) int running;

以上两段代码是相同的。

在setter方法中,采用直接赋值来实现设值操作:

-(void)setRunning:(int)newRunning{      _running = newRunning;  }

retian:在setter方法中,需要对传入的对象进行引用计数加1的操作。

简单来说,就是对传入的对象拥有所有权,只要对该对象拥有所有权,该对象就不会被释放。如下代码所示:

-(void)setName:(NSString*)_name{       //首先判断是否与旧对象一致,如果不一致进行赋值。       //因为如果是一个对象的话,进行if内的代码会造成一个极端的情况:当此name的retain为1时,使此次的set操作让实例name提前释放,而达不到赋值目的。       if ( name != _name){            [name release];            name = [_name retain];       }  }

strong:strong是在IOS引入ARC的时候引入的关键字,是retain的一个可选的替代。表示实例变量对传入的对象要有所有权关系,即强引用。strong跟retain的意思相同并产生相同的代码,但是语意上更好更能体现对象的关系。

weak:在setter方法中,需要对传入的对象不进行引用计数加1的操作。

简单来说,就是对传入的对象没有所有权,当该对象引用计数为0时,即该对象被释放后,用weak声明的实例变量指向nil,即实例变量的值为0。

注:weak关键字是IOS5引入的,IOS5之前是不能使用该关键字的。delegate 和 Outlet 一般用weak来声明。

copy:与strong类似,但区别在于实例变量是对传入对象的副本拥有所有权,而非对象本身。


原文转自:http://www.cocoachina.com/ios/20150123/11003.html

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 满脸的黑头痘痘怎么办 脚底磨起泡不敢走路怎么办 老婆老是找异性朋友怎么办 喜欢的人有对象怎么办 遇到了更喜欢的怎么办 8岁骨龄11岁怎么办啊 13岁初中生有思想不听话怎么办 交朋友找对象喜欢颜值高的怎么办 儿子找对象不听父母怎么办 缺爱怎么办的搞笑回答 对象说有人追她怎么办 说了一句话媳妇非常生气怎么办 柔顺后头发太臭怎么办 积分兑换手机被骗了怎么办 老板对你的上级不满怎么办 如果老板不给工资怎么办 手机号码被标记为其他公司怎么办? 被标记为骚扰电话怎么办 手机被标记骚扰电话怎么办 360摄像头不支持5g怎么办 摄像头不支持5g网络怎么办 家里的wifi卡了怎么办 办信用卡没有座机号码怎么办 拨打电话时显示号码有误怎么办 个体营业执照怎么办企业支付宝 没满16岁怎么办电话卡 我的电话卡丢了怎么办 公司注销地税没有补齐怎么办 公司没有固定电话怎么办信用卡 申请信用卡公司没有固定电话怎么办 办理信用卡公司没有固定电话怎么办 江门市固话欠费停机后怎么办 物业交钥匙地面有裂缝怎么办 深圳交通卡丢了怎么办 没装etc走etc怎么办 找不到过敏源身体痒怎么办 微信客服电话打不通怎么办 华为手机网络信号不好怎么办 酷我好友动态加载不了怎么办? 米兔电话手表停机了怎么办 糖猫电话手表停机了怎么办