2015年2月16日 星期一

學習Objective-C

Objective-C 是使用在iPhone程式開發的程式語言。你將花90%的時間在這個程式語言上。這個教學是為了讓程式設計師在短時間內掌握這個程式語言。假如你不知道要用什麼工具來開發iPhone程式,你可以先參考iPhone程式設計簡易教學
Objective-C 物件
Objective-C是一種物件導向的程式語言,你將花費很多時間在建立與使用物件上。定義物件只需要簡單地寫下類別名稱與一個用來指向物件的名稱就可以了:
NSNumber *numberObject;
NSNumber 在Objective-C中是一個一般常用的類別,這裡我們的物件名稱是numberObject。星號用來表示這個物件名稱是一個指標。
訊息物件
在Objective-C當你需要一個物件來作某件事時,你必須傳遞給它一個訊息。在其他的程式語言中,你可以把它叫做"呼叫方法",它的語法看起來像這樣:
alert.show();
Objective-C用訊息來作處理與其他程式語言有稍許的不同,我們將用傳遞訊息來取代呼叫方法。為了證明這個語法,我們用一個警告方塊當作例子。指定在上面出現的文字,警告方塊是一個一般的使用者介面元素,用來提示一個訊息讓使用者知道。在程式語言中不像dot net或Java,你可能會呼叫一個方法像"Show"來啟動這個對話方塊並顯示一段文字。為了作同樣的動作,在Objective-C你會寫成這樣:
[alert show];
首先你會看到物件與方法用一個方括號括起來。接著陳述將"show"這個訊息傳遞給"alert"這個物件。
帶參數的訊息傳遞
傳遞訊息常常會需要包含一個或多個參數。在其他程式語言中,它撰寫方式看起來像這樣:
alert.show("A Funny Message");
alert.show("A Funny Message", 3);
在Objective-C中,我們能作到相同的事,但我們需要包含描述的前置詞(指定在類別定義中)。例如,我們傳遞包含參數的訊息,我們就需要這樣寫:
[alert show:@"I say this!"];
[alert show:@"I say this!" thisManyTimes:3];
當你看到語法有點不同,你就能夠得到更多的資訊。對於許多Objective-C的初學者來說,這是個困擾人的問題,但你將會越來越習慣使用它。
Objective-C中的物件實體化
之前你已經知道如何讓物件工作,現在你要知道的是,建立物件的區域實體。這個過程叫做實體化,當你使用Objective-C時,你將需要在iPhone中分配記憶體來建立物件。你會傳送一個alloc訊息給類別它自己(你可以傳送訊息給物件與類別兩者)來配置記憶體。為了建立物件它自己,你將使用一個建構子,一般會前綴一個字"init"或簡單的初始化。
這裡是如何實體化一個物件(從現在起,我將在例子裡面使用一般化的描述字):
myClass *myObject = [[myClass alloc] init];
釋放物件
當你使用Objective-C時,在你建立、新增或複製物件後,你必須要釋放物件。這件事涉及記憶體管理我們將在下個部分作討論。釋放物件,你只需要簡單的傳送"release"訊息給物件。
[myObject release];
當你在Objective-C中使用物件時,你可以遵循下面這個規範:
//分配記憶體與建立物件
myClass *myObject = [[myClass alloc] init];
//使用物件
[myObject doStuff];
//釋放物件
[myObject release];
記憶體管理與參考計數
當你在iPhone中設計程式,你需要知道如何手動管理記憶體。這是個非常重要的議題,假如你沒有管理好記憶體,可能會導致內存洩漏或程式掛掉。管理iPhone記憶體的是一個簡單的系統叫做"參考計數"(reference counting)。
這個系統將會追蹤是否它需要保留記憶體,以使一個物件可以獲得。每一個元件藉由新增一個參考(有時候叫做保留)計數給物件,來指向它感興趣的物件。你可以藉由傳送"retain"訊息給一個物件,來新增一個物件參考計數。所以,假如5個元件對myObject感興趣,則myObject會有一個參考計數是5。這個系統會保留物件的記憶體,只要它的參考計數在0以上。

當元件不在為一個物件所需要時,他們將會移除他們對物件的感興趣,藉由傳送"release"訊息給物件。每次一個release訊息被傳送給物件時,物件它的參考計數會被減1。一但參考計數到達0時,系統會摧毀物件並在任何時候重新使用記憶體。

基本記憶體管理技巧

參考計數是一個簡單的系統。最重要的一件事是在你用關鍵字"alloc"建立物件的時候,記得要去釋放每個物件。每個alloc必須要有一個匹配的釋放動作。其他你必須要做的事是確認你傳送給物件的release訊息是否符合每個保留訊息。一但你完成一個物件,就須確認參考計數為0。假如你不想要浪費記憶體就需要這樣做。請不要在已經完成釋放且保留計數為0時,傳送訊息給物件。假如你這樣做會造成程式掛掉;這是一個開發常見的問題。

這裡有一個典型的物件生命週期的例子,每個期間參考計數都不一樣:
myClass *myObject = [[myClass alloc] init];
//參考計數: 1

[myObject retain];
//參考計數: 2

[myObject retain];
//參考計數: 3

[myObject release];
//參考計數: 2

[myObject release];
//參考計數: 1

[myObject release];
//參考計數: 0

一但myObject的參考計數到達0後,系統將會摧毀物件,且假如你企圖傳送一個訊息給myObject,你的程式將會掛掉。你必須小心的使用每一個alloc,並確保retain與release成對。假如你沒有這樣做,則你將會使得內存洩漏或導致程式掛掉。

NSString字串類別

咱們看看在Objective-C中很頻繁使用的一些類別與物件。查看XCode中的標頭檔來看看它能作什麼。

移到字串:在Objective-C中,你用來處理字串的類別叫做NSString,它能像其他物件一樣使用:
NSString *myString = [[NSString alloc] initWithString:@"A String"];
NSLog(myString);
[myString release];

筆記:在上面我們使用NSLog寫入訊息到控制台。這裡我們簡單地建立NSString的實體,用的是典型的模式描述(alloc, init& release)。然而,NSString有其他的函式是不需要你使用alloc或release訊息的。所以能用另一種寫法來完成這件事:
NSString *myString = @"A String";
NSLog(myString);

NSString也有函式來幫助你,將字串、數字與物件不同類型的變數連結成一個字串,這個函式就是stringWithFomat:
NSString *lotsOfInsertedStuffString = [NSString stringWithFormat:@"I am adding

this number: %i and this string:%@.", 45, myString];
NSLog(lotsOfInsertedStuffString);

NSString還有更多強大的函式,以可以在標頭檔中找到這些函式。

Objective-C中的計數與數字

有些時候你需要使用C風格的整數與浮點數來作數學運算。Objective-C 與C 常常在一起使用,特別是在處理數字的時候。在Objective-C中,你可以使用NSNumer類別,然而,當你需要命名數字時,你將會使用到C風格典型的程式設計活動,例如:迴圈、邏輯判斷式、case陳述、結構與函式。

C 整數與數字的使用:
int i = 3;
NSLog(@"i = %i", i);
double d = 3.4;
NSLog(@"d = %f", d);
double dPlusi = d + i;
NSLog(@"d + i = %f", dPlusi);

Objective-C 陣列使用類別NSMutableArray

在我們結束本文之前,來看一下如何使用物件導向的陣列。陣列可以看成是一個簡易的物件列表,在Objective-C中,你可以放任何東西到陣列裡面,你甚至可以混合或匹配物件。這裡有個如何使用陣列的例子:
//實體化一個陣列
NSMutableArray *myArray = [[NSMutableArray alloc] init];

//新增元素到一個陣列
[myArray addObject:@"Element 1"];
[myArray addObject:@"Element 2"];
[myArray addObject:@"Element 3"];

//從陣列中取得一個物件
NSLog([myArray objectAtIndex:0]);

//從陣列中取得最後一個物件
NSLog([myArray lastObject]);

使用陣列的理由是,你可以用for-each迴圈來對每個物件動作:
for (NSString *s in myArray) {
NSLog(s);
}
當然,當你不在使用陣列物件後,你必須釋放它。
[myArray release];

沒有留言: