property修饰符详解

1.关于@property

由于我们需要经常定义一些方法来访问成员变量,因此Objective-C提供了@property指令,来为我们自动生成setter和getter方法。

@property是编译器指令,在Xcode4.4之后,由@property修饰的成员变量会自动生成setter和getter方法的声明和实现。

不使用@property的情况下:

@interface Person : NSObject
{
    @public
    int _age;
    int _number;
}
@end

@implementation Person

-(void)setAge:(int) age{
    _age = age;
}
-(int)age{
   return _age;
}
-(void)setNumber:(int) number{
   _number = number;
}
-(int)number{
   return _number;
}
@end

int main(int argc, const char * argv[]) {

    Person *p = [Person new];
    [p setAge:30];
    NSLog(@"_number = %i, _age = %i", p->_number, p->_age);

    return 0;
}

使用@property的情况:

@interface Person : NSObject
    @property int age;
@end

@implementation Person

@end

int main(int argc, const char * argv[]) {

    Person *p = [Person new];
    [p setAge:30];
    NSLog(@"_number = %i, _age = %i", p->_number, p->_age);

    return 0;
}

现在:

@property int age;就可以代替setter和getter方法的声明和实现

注意:
(1)默认情况下,由@property生成的setter和getter方法会访问以""开头的成员变量,如果没有“”开头的成员变量,会自动生成一个以“—”开头的成员变量,自动生成的成员变量是私有变量,只能在本来中访问,不能在其它类中访问。
(2)@property只会生成最简单的getter和setter方法,而不会进行数据的处理和过滤。如果需要对数据进行判断需要我们重写getter/setter方法:
若重写了setter方法,编译器就只会生成getter方法;
若重写了getter方法,编译器就只会生成setter方法;
若同时重写了setter和getter方法,编译器就不会自动生成不存在的变量。

(3)点语法实际上就是调用成员变量的setter和getter方法,如果点语法在“等号”左边,那么会调用成员变量的setter方法,如果点语法在“等号”右边,那么会调用成员变量的getter方法。
(4)如果给一个属性同时提供了getter/setter方法,那么我们称这个属性为可读可写属性;
如果只提供了getter方法,那么我们称这个属性为只读属性;
如果只提供了setter方法,那么我们称这个属性为只写属性;

2.@property修饰符

书写格式:

@property(属性修饰符) 数据类型 变量名称;

2.1权限访问修饰符
readonly:只读属性,只会生成getter方法,不会生成setter方法。
readwrite:可以生成setter/getter方法,可读可写属性

使用方法:

@property (readonly) int age;

2.2内存管理
assign,retain
weak,strong

这四个修饰符都是和内存管理相关的修饰符

retain和assign:
在之前的文章中我们说过,在MRC模式下,我们需要手动管理内存即手动对对象的引用计数器进行加1或减1.

例如,当进行多个对象的内存管理时,set方法需要使用

-(void)setRoom:(Room *)room{
   if(_room != room){
         [_room release];   //需要将之前的取值释放掉
   }
   [room retain];   //当person对象使用room对象时,要对room对象的引用计数器加1
   _room = room;
}

为了方便我们开发,Objective-C为我们提供了retain修饰符
使用方法:

@property (retain) Room *room;

总结:因此,retain只能用来修饰对象,用retain修饰过的对象会自动生成内存管理的代码,且retain一般情况下都用在MRC模式下。

而assign刚好相反,assign只会生成普通的setter方法,并不会生成内存管理的代码

总结:assign不会生成内存管理的代码,不会增加引用计数,因此,assign既可以用来修饰基本类型(int float double NSInteger CGFloat,id等),也可以用来修饰对象类型。

weak和strong

在ARC(Automatical Reference Counting(自动引用计数))模式下,系统根据是否还有强指针指向当前对象判断是否释放当前对象。如果没有强指针指向当前对象,则系统会释放当前对象,如果没有强指针指向当前对象,则当前对象就会释放。

默认情况下,所有的指针都是强指针

例如:

{
    Person *p = [[Person alloc] init];
}
//因为p是局部变量,所以当大括号结束时,p会被回收,p回收之后,就没有强指针指向当前对象了,所以,大括号结束的时候,Person实例对象也会被释放。
{
    __strong Person *p = [[Person alloc] init];
    __weak p2 = p;
    p = nil;    //在这一行的时候Person实例对象会释放
}

在ARC中进行多对象的内存管理时,需要使用strong修饰符修饰另一个对象。

@property (strong) Dog *dog;

weak修饰符和strong修饰符相对,是弱指针的意思。用弱指针指向的对象会自动释放。

2.3 copy(深拷贝和浅拷贝)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章