码迷,mamicode.com
首页 > 其他好文 > 详细

Objective-C学习笔记_属性

时间:2015-08-02 20:04:13      阅读:125      评论:0      收藏:0      [点我收藏+]

标签:objective-c   ios   

一、属性

属性是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   ios   

原文地址:http://blog.csdn.net/u013485543/article/details/47210191

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!