属性在ios中的使用

来源:互联网 发布:淘宝 论坛 编辑:程序博客网 时间:2024/05/17 09:19

属性:

苹果公司在Objective-C 2.0中引进了属性(property)这个技术,它组合了新的预编译指令和属性访问器语法。新的属性功能明显减少了必须编写的冗余代码量。

注意:

在Objective-C 2.0的特性只适用于Mac OS X 10.5以上版本,如果必须支持旧的版本,则就不能使用属性功能了(至少目前是这样)另外,属性在ios开发中被广泛使用。

 

具体使用如下,重构子类AllWeatherRadial声明及实现:

声明部分:

#import "Tire.h"

@interface AllWealtherRadial : Tire

@property float rainHandling;

@property float snowHandling;

@end // AllWeatherRadial

 

实现部分:

#import "AllWealtherRadial.h"

@implementation AllWealtherRadial

@synthesize rainHandling;

@synthesize snowHandling;

 

- (id) initWithPressure:(float)p treadDepth:(float)td

{

if(self = [super initWithPressure:p treadDepth:td])

{

pressure = 23.7;

treadDepth = 42.5;

}

return (self);

}

 

- (NSString *) description

{

NSString *desc;

desc = [[NSString allocinitWithFormat:

@"AllWeatherRadial: %.1f / %.1f / %.1f / %.1f ",

[self pressure],[self treadDepth],

[self rainHandling],[self snowHandling]];

return (desc);

} // description

@end // tire

 

注意:

上面使用了属性@synthesize来替代原始的setter和getter自定义访问方法,而使用关键字@property来生成属性变量。另外,在Xcode 4.5以后版本中,可以不必使用关键字@synthesize了。

 

属性拓展:

在这里对Car类添加一个新的变量name,它代表着汽车的名字,代码如下所示:

声明部分:

#import <Cocoa/Cocoa.h>

@class Engine;

@class Tire;

 

@interface Car:NSObject

{

NSString *name;

Engine *engine;

NSMutableArray *tires;

}

@property (copyNSString *name;

@property (retainEngine *engine;

- (Tire *) tireAtIndex:(int) index;

- (void) setTire:(Tire *) tire atIndex:(int)index;

- (void) print;

@end // car

 

实现部分:

#import "Car.h"

#import "Engine.h"

#import "Tire.h"

@implementation Car

- (id) init

{

if(self == [super init]) 

    {

name = [[NSString allocinitWithString:@"Car"];

engine = [Engine alloc];

tires = [[NSMutableArray allocinit];

for(int i = 0;i < 4;i ++)

{

[tires addObject:[NSNull null]];

}

}

return (self);

}

@synthesize name;

@synthesize engine;

- (Tire *) tireAtIndex:(int)index

{

Tire *tire;

tire = [tires objectAtIndex:index];

return (tire);

}

- (void) setTire:(Tire *)tire atIndex:(int)index

{

[tires replaceObjectAtIndex: index withObject:tire];

}

- (void) dealloc

{

[name release];

[tires release];

[engine release];

[super dealloc];

}

 

- (void) print

{

NSLog(@"%@ has:",name);

for(int i =0;i < 4;i ++)

{

NSLog(@"%@",[self tireAtIndex:i]);

}

NSLog(@"%@",engine);

} // print

@end // car

 

上面的代码,使用了属性替代了原来的setter和getter方法,同时对引用的对象使用了保留和复制特性:

@property (copyNSString *name;

@property (retainEngine *engine;

 

名称的使用:

我们知道常用的做法是保持实例变量名与属性变量名相同,但有的时候,我们希望实例变量是一个名字,而公开的属性却是另一个名字。具体如下,修改Car类中的实例变量name为appellation,同时修改@synthesize指定新名字与老名字的关联即可:

声明部分:

@class Engine;

@class Tire;

@interface Car:NSObject

{

NSString *appellation;

Engine *engine;

NSMutableArray *tires;

}

@property (copyNSString *name;

@property (retainEngine *engine;

- (Tire *) tireAtIndex:(int) index;

- (void) setTire:(Tire *) tire atIndex:(int)index;

- (void) print;

@end // car

实现部分:

#import "Car.h"

#import "Engine.h"

#import "Tire.h"

@implementation Car

- (id) init

{

if(self == [super init]) {

self.name = [[NSString allocinitWithString:@"Car"];

engine = [Engine alloc];

tires = [[NSMutableArray allocinit];

for(int i = 0;i < 4;i ++)

{

[tires addObject:[NSNull null]];

}

}

return (self);

}

@synthesize name = appellation;

@synthesize engine;

- (Tire *) tireAtIndex:(int)index

{

Tire *tire;

tire = [tires objectAtIndex:index];

return (tire);

}

- (void) setTire:(Tire *)tire atIndex:(int)index

{

[tires replaceObjectAtIndex: index withObject:tire];

}

- (void) dealloc

{

[self.name release];

[tires release];

[engine release];

[super dealloc];

}

 

- (void) print

{

NSLog(@"%@ has:",self.name);

for(int i =0;i < 4;i ++)

{

NSLog(@"%@",[self tireAtIndex:i]);

}

NSLog(@"%@",engine);

} // print

@end // car

 

很明显,在实现代码中,我们将name和appellation关联了起来:

@synthesize name = appellation;

实际上,编译器依然创建setName和name方法,但实际上用的却是新的appellation实例变量,编译时会遇到问题,所以解决的办法是将实例变量的直接访问改为访问方法,如:self.name,这种做法就可以消除编译器歧义,使其知道使用访问方式获得变量。

 

只读属性使用:

我们知道对象的属性是可变的,即可以读取也可以修改的。我们可以使用readwrite特性。对象默认的属性为readwrite,一般不会用到它,但为了表明自己的用意,建议填上这个属性特性。具体如下,我们修改Car类,让它支持属性特点实现:

@property (readwritecopyNSString *name;

@property (readwriteretainEngine *engine;

 

注意:

A、我们有时会使用属性readonly,如果修改了该属性对象,那么编译器就会报错。

B、如果我们不想编译器自动生成变量、setter及getter,那么可以使用@dynamic来修饰实例变量。

C、特性不是万能的,从之前的例子中可以知道,我们并没有提供转换tire对象的访问方法以支持属性。

- (Tire *) tireAtIndex:(int)index

{

 

Tire *tire;

tire = [tires objectAtIndex:index];

return (tire);

}

- (void) setTire:(Tire *)tire atIndex:(int)index

{

[tires replaceObjectAtIndex: index withObject:tire];

}

因为这些方法不能适应属性所覆盖的较小范围。属性只支持替代setter及getter方法。

 

好了,属性的使用就总结到这里。

 

 

/**

*  技术交流群:179914858

*/

 

0 0