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(深拷貝和淺拷貝)

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