@property是什么
@Property是聲明屬性的語法,它可以快速方便的為實例變量創建存取器,并允許我們通過點語法使用存取器。
存取器(accessor):指用于獲取和設置實例變量的方法。用于獲取實例變量值的存取器是getter,用于設置實例變量值的存取器是setter。
創建存取器
手工創建存取器
我們先看兩段代碼:
//Fraction.h
#import <Foundation/Foundation.h>
@interface Fraction:NSObject
{
int numerator;
int denominator;
}
-(void) print;
-(void) setNumerator: (int) n;
-(void) setDenominator: (int) d;
-(int) numerator;
-(int) denominator;
-(double) convertToNum;
上面代碼中numerator、denominator是Fraction類的實例變量,并且看到對這兩個實例變量都聲明了set/get方法。
//Fraction.m
#import "Fraction.h"
@implementation Fraction
-(void) print
{
NSlog (@"%i/%i", numerator, denominator);
}
-(void) setNumerator: (int) n
{
numerator=n;
}
-(void) setDenominator: (int) d
{
denominator=d;
}
-(int) numerator
{
return numerator;
}
-(int) denominator
{
return denominator;
}
-(double) convertToNum
{
if (denominator != 0)
return (double) numerator / denominator;
else
return 1.0;
}
@end
上面代碼是對實例變量存取器的實現。我們可以看到,存取器就是對實例變量進行賦值和取值。按照約定賦值方法以set開頭,取值方法以實例變量名命名。
使用@Property創建存儲器
@interface Fraction:NSObject
{
int numerator;
int denominator;
}
@property int numerator, denominator;
-(void) print;
-(double) convertToNum;
上面代碼中,我們使用@property聲明兩個屬性,名稱與實例變量名稱相同。
@implementation Fraction
@synthesize numerator, denominator;
-(void) print
{
NSlog (@"%i/%i", numerator, denominator);
}
-(double) convertToNum
{
if (denominator != 0)
return (double) numerator / denominator;
else
return 1.0;
}
@end
和手動生成存取器相比,在.m文件中我們使用@synthesize自動生成這兩個實例變量的存取器,并且隱藏了存取器,雖然我們看不到存取器,但它們確實是存在的。
總結:
@property等同于在.h文件中聲明實例變量的get/set方法,@synthesize等同于在.m文件中實現實例變量的get/set方法。使用@property和synthesize創建存取器要比手動聲明兩個存取方法(getter和setter)更簡單。而且我們在使用屬性時可以使用點語法賦值或取值,語法更簡單,更符合面向對象編程。
不必單獨聲明實例變量
如果我們希望使用默認的實例變量命名方式,那么我們在.m文件中就不需要使用@synthesize聲明,系統會幫我們自動完成(以“_實例變量名字”來命名)。
@synthesize numerator = _numerator;
@synthesize denominator = _denominator;
如果我們希望自己命名實例變量命,那么我們就使用@synthesize顯示聲明我們希望的實例變量名。
@property的特性
@property還有一些關鍵字,它們都是有特殊作用的,比如上述代碼中的nonatomic,strong。
把它們分為三類,分別是:原子性,存取器控制,內存管理。
原子性
atomic(默認):atomic意為操作是原子的,意味著只有一個線程訪問實例變量。atomic是線程安全的,至少在當前的存取器上是安全的。它是一個默認的特性,但是很少使用,因為比較影響效率,這跟ARM平臺和內部鎖機制有關。
nonatomic:nonatomic跟atomic剛好相反。表示非原子的,可以被多個線程訪問。它的效率比atomic快。但不能保證在多線程環境下的安全性,在單線程和明確只有一個線程訪問的情況下廣泛使用。
存取器的控制
readwrite(默認):readwrite是默認值,表示該屬性同時擁有setter和getter。
readonly: readonly表示只有getter沒有setter。
內存管理
主要涉及到assign、retain、strong、weak、copy等情況,以及各自的使用場景。
Strong:強引用,表示實例對象對傳入的對象有所有權關系。常用在:自定義對象,控制器對象。
Weak:弱引用,在setter方法中,需要對傳入的對象不進行引用計數加1的操作,也就是,對傳入的對象沒有所有權,當該對象的引用計數為0時,該對象即被釋放,用weak聲明的實例變量指向nil,即實例變量的值為0。常用在:delegate對象,IBOutLet。
Assign:簡單賦值,不改變引用計數,適合簡單數據類型如NSInteger、CGFloat、int、float等。
Copy:把原來的對象完整復制另外一個地方,重新加載內存區,原來對象變了不影響新內存區的對象。常用在:NSString、NSArray、NSDictionary及其子類等。