@property 的使用

在物件導向設計方法中我們會使用封裝來保護類別成員(成員亦包含了attribute與method),我們通常會寫method來存取attribute,命名為getter與setter,以下示範objective C的getter setter作法:

A.h

#import <Foundation/Foundation.h>

@interface A : NSObject {

int attr;

}

-(int)attr; //習慣上objective C不會在getter寫上get, 而是直接使用attribute作為getter

-(void)setAttr:(int)a;

@end

A.m

#import "A.h"

@implementation A

- (int)attr {

return self->attr; //原則上不加self也可以, 加了就可以跟method內的變數作區隔

}

-(void)setAttr: (int) a {

self->attr = a;

}

@end

當你使用以上的寫法作為getter與setter時,您在程式中使用實體物件時,就可以用"."的方式來作存取, 方在 assignment的左邊代表setter, 在右邊代表getter,示範如下:

main.m

#import <Foundation/Foundation.h>

#import "A.h"

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

A *a = [A alloc];

[a.attr 30]; // assign 30 給這個物件的attribute

printf("The attribute of A is %d", a.attr); //取出a.attr的值, 會印出The attribute of A is 30

[a release];

}

是不是每次都要用傳統的作法才能達成"."的取用呢? 其實Objective C安排了一個比較簡單的作法,就是@property,那為甚麼要先介紹上面的做法呢?很簡單因為使用任何捷徑都應該先知道他的原理吧?知道了原理未來才不會在debug中苦哈哈。使用@property的寫法如下:

A.h

#import <Foundation/Foundation.h>

@interface A : NSObject {

int attr;

}

@property int attr; //這樣就會自動建立gettery與setter

@end

A.m

#import "A.h"

@implementation A

@synthesize attr; // 舊版的xcode需要成雙寫property與synthesize,新版的只要寫property其實就可以了,

//synthesize可以讓你改property的名字, 寫法是 @synthesize attr = ppp; (就改成ppp了)

@end

main.m

#import <Foundation/Foundation.h>

#import "A.h"

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

A *a = [A alloc];

[a.attr 30]; // 一樣可以使用

printf("The attribute of A is %d", a.attr); //取出a.attr的值, 會印出The attribute of A is 30

[a release];

}

基本上使用@property 會自動作三件事情:

  1. 建立了 setPropertyName (setter)
  2. 建立了 propertyName (getter)
  3. 建立了 propertyName (attribute)
*這些method是可以被override的, 所以使用了@property後, 你也可以改寫成自己想用的方式。
@property的設定 //用來設定property的參數
讀寫控制
  1. readwrite (預設): 可以讀寫,setter和getter方法都會自動加入
  2. readonly: 只能讀, 只會加getter的方法

setter相關部分

  1. assign(預設): 用於只會和可量度的數值作用的情況, _abc = b;
  2. retain/strong 在指定時會呼叫物件的retain指令, 然後前一個數值會release掉
  3. copy: 在指定時會呼叫物件的copy指令, 然後前一個數值會release掉 (一定要實作NSCopy的Protocol, 否則會掛點)
atomicity (單一性)
  1. atomic (預設): 會讓屬性有執行緒安全(thread-safe)的特性
  2. nonatomic: synthesize的存取者會直接回傳數值

基礎

  1. Objective C其實是C的superset,所有之前學過的C語言語法在Objective C裡面都可以使用,而Objective C為C增加了一些功能。
  2. 學習Objective C有個要注意的地方,它不像.NET與JAVA那樣會有系統作Garbage Collection,一切記憶體管理都要自己來。
  3. 建議在建立Objective C專案的時候不要使用Automatic Reference Counting,因為他並不是像Garbage Collection那麼的自動化,純粹只是在編譯的時候幫你加一些跟記憶體相關的statement而已,處理不好可能還會造成memory的問題。
  4. 為甚麼Objective C的NSString,NSOject這些物件前面都有"NS"? 其實NS的是"NeXtStep" 的縮寫, 由這家公司所開發的程式語言。
  5. Nil 與 Null的差別?Nil是一個物件,他可以被操作[nil message],但NULL就是一個空物件,操作空的物件程式會死掉,但nil不會。
  6. include的部分 < … > 與 ""…"" 的差別? 前者是系統提供的.h檔,後者是使用自己建立的。
  7. NSLog 與 printf 的差別? NSLog 是真的會寫進程式日誌檔,所以如果只是平常程式debug其實可以用printf (如果不是寫iOS的話)
  8. NSString 的表示方法 @"…" 與 C的char array 用法完全不同, 不能當成同一種東西。
  9. 變數的命名要有意義,原則上如果程式碼寫得夠好,它本身就是一個註解。

使用方法 Method

  1. [myObject someMethod:argument];
  2. 它不像JAVA是用 "." (如 myObject.someMethod), "." 在Objective C有別的意義存在,稍後會解釋。
  3. Method的參數寫法相當特別,它的原意是希望整個Method念起來就像一個句子一樣,參數之間用空格間隔,格式如下:
    -(void)setBrand:(NSString *)brandname isA:(NSString *)type whichcost:(int) price;

Header File

  1. 用來宣告這個物件/協定有哪些成員(如attribute與method),記得在Objective C中不能制定初值(慣性上會在init裡面作初值的指定)
  2. 格式如下:(import後面不需要分號), attribute都是包在{ }之間,method寫在{}之後,"-" 代表的是實體方法。"+"代表的是靜態方法
#import <Foundation/Foundation.h>
@interface A : NSObject {
NSString *brand;
CGFloat size;
BOOL power;
NSDate *creationDate;
}
-(void)ma;
@end
補充: 一般上我們的認知是void是一種不會回傳東西的方法,但事實上(void)本身就是一個型態,回傳的也是void。

建立實體物件的方式

  1. 儘量不要用 new, 用 alloc, 因為 new 其實包含了兩個動作: alloc 加 init, 並不是所有的物件都會以init開始, 可能會initWithXXX, 所以與其這樣不如就自己alloc之後再挑init的方法,我們常看到的寫法就會這樣:
A *a = [[A alloc] init];
[a release]; //物件都要記得release, 他們會成對出現