Objective-C_属性
来源:互联网 发布:aion捏脸数据 编辑:程序博客网 时间:2024/05/17 06:34
一、属性
属性是Objective-C 2.0定义的语法,为实例变量提供了setter、getter方法的默认实现。能在一定程度上简化程序代码,并且增强实例变量的访问安全性。
属性的声明
与类相似,属性也需要声明和实现。
属性的声明:使用@property声明属性
例如:@property NSString *name;
相当于 @interface 中声明了两个方法(setter、getter):
- (void)setName:(NSString *)name;- (NSString *)name;
属性的实现
属性的实现:使用@synthesize实现属性
例如:@synthesize name = _name;
相当于 @implementation 实现了setter、getter
- (void)setName:(NSString *)name{ _name = name;}- (NSString *)name{ return _name;}
注意:
原先 @property 声明与实现文件中的另一个声明 @synthesize 相结合,来完成setter、getter方法的创建。Xcode4.5之后 @synthesize 会在内部自动生成,不用手动添加。但是,如果属性 @property 声明之后,要在.m实现文件中重写setter、getter方法,则必须在.m实现文件中添加 @synthesize。
属性声明后,重写setter、getter方法,声明@synthesize的示例代码如下:
#import <Foundation/Foundation.h>@interface Person : NSObject@property NSString *name;- (void)setName:(NSString *)name;- (NSString *)name;@end#import "Person.h"@implementation Person/* 属性声明后,重写setter、getter方法,必须声明@synthesize */@synthesize name = _name;- (void)setName:(NSString *)name{ _name = name;}- (NSString *)name{ return _name;}@end
二、属性的属性(Attribute)
Objective-C提供属性的目的是为了简化程序员编码,为属性提供了一些关键字⽤以控制setter、getter的实现细节,这些关键字我们称为属性的属性(attribute)。属性的属性一共3大类。
第一类:读写性控制(readonly、readwrite、setter、getter)
readonly
,告诉编译器,只声明getter方法(无setter方法)。
例如:@property (readonly) NSString *name; //等价于 - (NSString *) name;
readwrite
,告诉编译器,既声明setter⼜声明getter。
例如: @property (readwrite) NSString *name; //等价于 - (NSString *) name; - (void)setName:(NSString *)name;
,读写性控制的默认设置。
setter = 方法名
,指定设置器的方法名。
getter = 方法名
,指定访问器的方法名。
第二类:原子性控制(nonatomic、atomic)
atomic
,setter、getter方法在多线程访问下是绝对安全的,即setter、getter内部做了多线程访问处理。原⼦子性控制的默认设置是atomic。
nonatomic
,setter、getter方法内部不会做多线程访问处理,仅仅是普通的setter、getter⽅法。
程序开发过程中,setter、getter处处都在用,如果使用atomic,需要不断对setter、getter加锁解锁以保证线程访问安全,会很占用系统资源,降低系统性能。通常设置为nonatomic,某些属性需要线程安全的时候,才定义为atomic。
例如:
@property (readwrite, nonatomic) NSString *name;//等价于- (NSString *)name;- (void)setName:(NSString *)name;
第三类:语义设置(assign、retain、copy)
assign
,setter、getter内部实现是直接赋值,适用于基本数据类型,默认值。
例如:
@property (nonatomic, assign) NSString *name;- (void)setName:(NSString *)name{ _name = name;}- (NSString *)name{ return _name;}
retain
,setter、getter的内部实现会做内存优化,适用于对象类型。
例如:
@property (nonatomic, retain) NSString *name;- (void)setName:(NSString *)name{if(_name != name){ [_name release]; _name = [name retain];}}- (NSString *)name{ return [[_name retain]autorelease];}
copy
,setter、getter的内部实现也会做内存优化,复制一个副本,适用于特殊的对象类型,一般适用于NSSting。
例如:
@property (nonatomic, copy) NSString *name;- (void)setName:(NSString *)name{if(_name != name){ [_name release]; _name = [name copy]; }}- (NSString *)name{ return [[_name retain]autorelease];}
小结:
- 如果属性是⾮对象类型(比如int,float等)属性的语义设置使用assign。
- 如果属性是对象类型(⽐如NSStrng、NSArray等)属性的语义设置使用retain。
- 如果属性是对象类型并且想得到参数的copy,使用copy关键字。
三、点语法
点语法是Objective-C 2.0中定义的语法格式。提供了⼀种便捷的属性访问⽅式。
点语法的使用
凡是符合系统默认setter、getter书写格式的方法都可以使用点语法。
例如:[person1 setName:@”ZhangSan”];
可以等价写成person1.name = @”ZhangSan”;
。
NSString *name = [person1 name];
可以等价写成NSString *name = person1.name;
属性是一对getter、setter方法,点语法是属性的另一种调用格式。
四、KVC
KVC(Key-Value-Coding),键值编码,是一种间接访问实例变量的方法。
key:键,用于标识实例变量。
vlaue:实例变量对应的值。
修改值
- setValue:forKey:
- setValue:forKeyPath:
- setValue:forUndefinedKey:
- setValuesForKeysWithDictionary:
获取值
- valueForKey:
- valueForKeyPath:
- valueForUndefinedKey:
注意事项
当key不存在的时候,会执行setValue:forUndefinedKey:
系统默认实现是抛出一个异常
为了更好的体验KVC的用途,以下是示例代码:
要求
定义一个Classroom类: 实例变量: 教室编号, 学生(Person类)
实例变量不写setter, getter方法
Classroom.h文件代码如下:
#import <Foundation/Foundation.h>@class Person;@interface Classroom : NSObject{@protected NSString *_classNum; Person *_student;}#pragma mark - 重写父类方法- (void)setValue:(id)value forUndefinedKey:(NSString *)key;- (id)valueForUndefinedKey:(NSString *)key;@end
Classroom.m文件代码如下:
#import "Classroom.h"#import "Person.h"@implementation Classroom- (void)setValue:(id)value forUndefinedKey:(NSString *)key{ NSLog(@"无此实例变量: %@", key);}- (id)valueForUndefinedKey:(NSString *)key{ NSLog(@"无此实例变量: %@", key); return nil;}@end
Person.h文件代码如下:
#import <Foundation/Foundation.h>@interface Person : NSObject/* 实例变量 */{@protected NSString *_name; NSInteger _age;}#pragma mark - 属性的声明/* 代码规范: 属性的名字没有 _ * 属性包含三部分内容: 实例变量, 实例变量的setter方法, 实例变量的getter方法 */@property NSString *hobby;@property NSString *sex;#pragma mark - 属性的属性(特性)/* 第一类 attribute: 读写性控制 * readonly: 相当于只提供了getter方法 * readwrite: 相当于提供了setter 和 getter方法 * 默认: readwrite * 通常设置: readwrite *///@property (readonly) NSString *name;/* 第二类: attribute: 原子性控制 * atomic: 原子性 * nonatomic: 非原子性 * 默认: atomic * 通常设置: nonatomic */@property (readwrite, nonatomic) NSString *height;/* 第三类 attribute: 语义设置 * assign: 非对象类型使用: int, float, NSInteger * retain: 对象类型使用: NSString, NSArray, 会对setter, getter方法进行内存优化 * copy: 对象类型使用, 对setter, getter方法进行内存优化 * 默认: assign */@property (readwrite, nonatomic, assign) NSInteger weight;@property (readwrite, nonatomic, retain) NSString *marry;@property (readwrite, nonatomic, copy) NSString *work;/* 通常的属性声明 */@property (nonatomic, retain) NSString *blood;#pragma mark -/* 实例变量setter, getter方法 */- (void)setName:(NSString *)name;- (NSString *)name;- (void)setAge:(NSInteger)age;- (NSInteger)age;@end
Person.m文件代码如下:
#import "Person.h"@implementation Person#pragma mark - 属性的实现/* 相当于实现了 setter 和 getter 方法 * 可以省略 @synthesize 一行 */@synthesize hobby = _hobby;@synthesize sex = _sex;- (void)setName:(NSString *)name{ _name = name;}- (NSString *)name{ return _name;}- (void)setAge:(NSInteger)age{ _age = age;}- (NSInteger)age{ return _age;}@end
main.m文件代码如下:
#import <Foundation/Foundation.h>#import "Person.h"#import "Classroom.h"int main(int argc, const char * argv[]) { @autoreleasepool { /* 定义一个Classroom类: 实例变量: 教室编号, 学生(Person类) * 实例变量不写setter, getter方法 */ /* 创建一个Person对象, 一个Classroom对象 */ Person *stu = [[Person alloc] init]; Classroom *classroomOne = [[Classroom alloc] init]; /* 使用KVC赋值 */ [classroomOne setValue:@"5211" forKey:@"_classNum"]; [classroomOne setValue:stu forKey:@"_student"]; [classroomOne setValue:@"5212" forKey:@"classroomNum"]; [classroomOne setValue:@"dd" forUndefinedKey:@"sss"]; [classroomOne setValue:@"ZhangSan" forKeyPath:@"_student.name"]; /* 使用KVC取值 */ NSLog(@"classNum: %@", [classroomOne valueForKey:@"_classNum"]); NSLog(@"student name: %@", [classroomOne valueForKeyPath:@"_student.name"]); NSLog(@"student name: %@", [classroomOne valueForKeyPath:@"_student002"]); } return 0;}
- Objective-C_属性
- Objective-C_类
- Objective-C_字面量
- Objective-C_数据字典,集合
- Objective-C_类和对象
- Objective-C_分数类实现
- Objective-C_内存管理(一)
- Objective-C_内存管理(二)
- Objective-C_类的扩展
- Objective-C_语言 练习题2
- Objective-C_语言_NSNotification(通知)
- Objective-C_语言_类目
- Objective-C_语言_延展
- Objective-C_语言_协议
- Objective-C_语言_计算机网络
- Objective-c_搭建windows下编程环境
- Objective-C_初始类和对象
- Objective-C_继承_初始化方法
- C语言-递归算法以及经典递归(Hanoi)
- 霓虹灯Demo
- VS2013中添加对多字符集的支持
- 视图控制器的主要方法
- java中怎样在界面中显示图片?
- Objective-C_属性
- 什么是 Java 中的内部类
- 51Nod 1189 阶乘分数 (数论)
- HDU1224 Free DIY Tour(spfa+记录路径)
- 字符串拷贝操作
- Quotient Polynomial
- 精灵进程的创建
- Javascript-基础知识(4)
- java中的异常详解