IOS——開發語言(一)

注:本文學習資源來自本站資料。

摘要:iOS是由蘋果公司爲iPhone、iPad等移動設備開發的操作系統,2010年6月更名爲iOS。iOS的系統架構分爲四個層次:核心操作系統層,核心服務層,媒體層,可輕觸層。應用程序由Objective-C語言開發。

一直以來都覺得蘋果的系統很神奇,其實對蘋果的操作系統不是很瞭解,今天有幸也有興看到講述IOS的一套東西,拿過來做個專題的總結和學習:

Objective-C基礎語法的快速入門:

Objective-C是Mac軟件開發領域最主要的開發語言,假如我們對面向對象的思維已經C語言都很熟悉的話,對於我們學習Objective-C將會非常有用。假如我們對C語言還不熟悉的話,那我們需要學習一下C語言。

方法調用:

爲了能夠儘快上手,我們先來看一些簡單的例子。Objective-C語法裏面基本的方法調用是這樣的:

  1. [object method];
  2. [object methodWithInput:input];

對象的方法可以返回值:

  1. output = [object methodWithOutput];
  2. output = [object methodWithInputAndOutput:input];

我們也可以在類裏面調用如何創建對象的方法。下面的這個例子裏面,我們調用了NSString類的string方法:

  1. id myObject = [NSString string];

id的類型意味着myObject這個變量可以指向任意類型的變量。當我們編譯這個應用程序的時候,並不知道他實現的真實的類和方法。

在這個例子裏面,很明顯這個對象的類型應該是NSString,所以我們可以改一下他的類型:

  1. NSString* myString = [NSString string];

現在myString就是一個NSString類型的變量。這個時候假如我們試圖使用一個NSString沒有實現的方法時,編譯器就會警告我們。

一定要注意在對象類型的右邊有一個星號。所有的Objective-C對象變量都是指針類型的。id類型已經預先被定義成一個指針類型了。所以我們不需要再加星號。

嵌套消息調用(Nested Messages):

在許多編程語言裏面嵌套消息,或者嵌套函數看起來就像這樣:

  1. function1 ( function2() );

function2的返回值被傳遞給function1當輸入參數。在Objective-C裏面,嵌套消息調用就像這樣:

  1. [NSString stringWithFormat:[prefs format]];

我們應該儘量避免在一行代碼裏面嵌套調用超過兩個。因爲這樣的話,代碼的可讀性就不太好。

多參輸入的方法:

多個輸入參數的方法。在Objective-C裏面,一個方法名可以被分割成幾段。在頭文件裏面,就應該這樣子來定義一個多輸入參數的方法:

  1. -(BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;

我們這樣來調用它:

  1. BOOL result = [myData writeToFile:@"/tmp/log.txt" atomically:NO];

參數不一定要給它命名。在運行期系統裏面這個方法真實的名字叫writeToFile:atomically:。

  1. Accessors(Getter & Setter)

在Objective-C裏面所有的實例對象默認都是私有的。所有在大多數情況下我們需要用accessors去讀取或者設置變量的值。有兩個語法都支持這樣的操作,這個時傳統的老的語法:

  1. [photo setCaption:@"Day at the Beach"];
  2. output = [photo caption];

第二行的代碼其實並非直接去讀對象實例的變量。事實上它調用的是名叫caption的方法。在Objective-C裏大多數情況下我們不需要給getters加get的前綴。

無論什麼時候我們見到方括號,其實我們都是向一個對象或者一個類發送了一個消息。

Dot Syntax:

在Objective-C 2.0裏面,新增加了一個"."操作的語法。在Mac OS X 10.5裏面就使用了Objective-C 2.0語法:

  1. photo.caption = @"Day at the Beach";
  2. output = photo.caption;

我們兩種方式都可以使用。但是在一個工程裏面最好保持風格一致,只使用某一種。"."操作只能夠被使用在setters和getters裏面,而不能用在一般意思的方法上。

創建對象:

主要有兩種方式來創建一個對象。第一種辦法像這面這樣:

  1. NSString* myString = [NSString string];

這是一種非常習慣性的風格。在這種方式情況下,我們創建的是系統自動釋放(autoreleased)類型的對象。關於自動釋放類型autoreleased,我們以後會深入討論一下。然而在許多情況下,我們需要手動的去創建對象:

  1. NSString* myString = [[NSString alloc] init];

這是一個嵌套的方法調用。第一個調用的NSString自己的alloc方法。這是一個相對比較底層的調用,因爲他創建了內容,以及實例化了一個對象。

第二塊代碼調用了新創建對象的init方法。這個init方法實現了比較常用的基本設置,比如創建實例對象的參數。對於一般開發人員而言,實現這個客戶的類的具體的細節並不清楚。

在一些情況下,我們可以用不通的初始化方式去賦初值:

  1. NSNumber* value = [[NSNumber alloc] initWithFloat:1.0];


基本的內存管理:

假如我們正在爲Mac OS X開發一個應用程序,我們可以選擇是否啓用垃圾回收機制。這就意味着我們不需要去考慮內存管理,除了一個特別複雜的情形我們需要處理一下。

然而,我們有的時候我們的開發環境沒有垃圾回收機制,比如iPhone開發的時候就沒有垃圾回收機制。在這種情況下,我們就需要了解一些基本的內存管理方面的概念。

假如我們手動的通過alloc創建了一個對象,我們需要用完這個對象後release它。我們不需要手動的去release一個autoreleased類型的對象,假如真的這樣去做的話,我們的應用程序將會crash。

這裏有兩個例子:

  1. // string1 will be released automatically
  2. NSString* string1 = [NSString string];
  3. // must release this when done
  4. NSString* string2 = [[NSString alloc] init];
  5. [string2 release];

就這個教程而言,我們可以人爲autoreleased對象會在當前函數方法調用完成後被釋放。

當然了,還有很多關於內存管理的只是我們需要學習,但是這需要我們瞭解更多的基本概念以後才能去涉及。

設計一個類的Interface:

就Objective-C語言而言,創建一個類非常簡單。它非常典型的分成了兩個部分。

類的接口通常保存在ClassName.h文件裏,它定義了實例的參數,以及一些公開的方法。

類的實現在ClassName.m文件裏。它包含了真正運行的代碼和那些方法。它還經常定義一些私有的方法。這些私有的方法對於子類是不可見的。

這裏有一個接口文件的大概。類名Photo,所以文件名叫Photo.h:

  1. #import
  2. @interface Photo : NSObject {
  3. NSString* caption;
  4. NSString* photographer;
  5. }
  6. @end

首先,我們把Cocoa.h import進來。Cocoa的應用程序的所有的基本的類大多都是這樣做的。#import宏指令會自動的避免把同一個文件包含多次。

@interface符號表明這是Photo類的聲明。冒號指定了父類。上面這個例子父類就是NSObject。

在大括弧裏面,有兩個變量:caption和photographer。兩個都是NSString類型的。當然了,他們也可以是任何別的類型包括id類型的。

最後@end結束整個聲明。

增加方法:

讓我們爲成員變量加一些getters:

  1. #import
  2. @interface Photo : NSObject {
  3. NSString* caption;
  4. NSString* photographer;
  5. }
  6. - caption;
  7. - photographer;
  8. @end

別忘記,Objective-C方法不需要加get前綴。一個單獨小橫杆表明它是一個實例的方法。假如是一個加號的話,那就說明它是一個類的方法。

編譯器默認的方法的返回類型爲id。還有所有的方法的參數的默認類型也都是id類型的。所以上面的代碼從技術上講是對的。但是很少這麼用。我們還是給它加上返回類型吧:

  1. #import
  2. @interface Photo : NSObject {
  3. NSString* caption;
  4. NSString* photographer;
  5. }
  6. - (NSString*) caption;
  7. - (NSString*) photographer;
  8. @end

下面我們再加上setters:

  1. #import
  2. @interface Photo : NSObject {
  3. NSString* caption;
  4. NSString* photographer;
  5. }
  6. - (NSString*) caption;
  7. - (NSString*) photographer;
  8. - (void) setCaption: (NSString*)input;
  9. - (void) setPhotographer: (NSString*)input;
  10. @end

Setters不需要返回任何值,所以我們把它的類型指定爲void.

類的實現:

我們通過實現getters來創建一個類的實現:

  1. #import "Photo.h"
  2. @implementation Photo
  3. - (NSString*) caption {
  4. return caption;
  5. }
  6. - (NSString*) photographer {
  7. return photographer;
  8. }
  9. @end

這部分的代碼由@implementation再來加上類名開始,以@end結束。就跟類的接口定義一樣,所有的方法跟接口定義裏的一樣。所有的對象都必要既要定義也要實現。

假如我們以前也寫過代碼的話,Objective-C裏面的getters看上去跟別的差不多。所以我們下面就來介紹setters,它需要一點說明。

  1. - (void) setCaption: (NSString*)input
  2. {
  3. [caption autorelease];
  4. caption = [input retain];
  5. }
  6. - (void) setPhotographer: (NSString*)input
  7. {
  8. [photographer autorelease];
  9. photographer = [input retain];
  10. }

每個setter處理兩個變量。第一個是當前存在對象的應用。第二個是新的輸入對象。在支持垃圾回收的開發環境裏,我們只要直接賦新值就可以了:

  1. - (void) setCaption: (NSString*)input {
  2. caption = input;
  3. }

但是假如我們不可以用垃圾回收機制的話,我們就需要先retain舊的對象,然後retain新的對象。

有兩種方法可以釋放一個引用對象:release 和 autorelease。標準的release會直接刪除引用。autorelease方法會在將來的某個時候去release它。在它聲明週期結束前,它會毫無疑問的存在。在本例中,上面setPhotographer中的photographer對象,將會在函數結束的時候被釋放。

在setter裏面用autorelease是安全的,因爲新對象跟老的對象有可能是同一個對象有可能指向的是同一個對象。對於一個我們即將retain的對象,我們不應該立即release它。

這個也許現在看起來會困惑,但是隨着我們的學習,會越來越能理解它。現在我們不需要立刻完全理解它。

初始化:

我們可以創建一個初始化方法去給類的實例的成員變量賦初值:

  1. - (id) init
  2. {
  3. if ( self = [super init] )
  4. {
  5. [self setCaption:@"Default Caption"];
  6. [self setPhotographer:@"Default Photographer"];
  7. }
  8. return self;
  9. }

上面的代碼感覺沒啥好解釋的,雖然第二行代碼好像看上去沒啥用。這個是一個單等於號,就是把[super init]的值賦給了self。

它基本上是在調用父類去實現它的初始化。這個if代碼段是設置默認值之前驗證初始化是否成功。

釋放資源:

這個dealloc方法是在當一個對象希望被從內容裏面刪除的時候調用。這個我們釋放在子類裏面引用成員變量的最好的時機:

  1. - (void) dealloc
  2. {
  3. [caption release];
  4. [photographer release];
  5. [super dealloc];
  6. }

開始兩行我們發送了release通知給了兩個成員變量。我們不要在這裏用autorelease。用標準的release更快一點。

最後一行的[super dealloc];非常重要。我們必須要發送消息去讓父類清除它自己。假如不這麼做的話,這個對象其實沒有被清除乾淨,存在內存泄露。

dealloc在垃圾回收機制下不會被調用到。取而代之的是,我們需要實現finalize方法。

 

 

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