Objective-C入門

發布時間: 2011-02-19 20:59  閱讀: 80711 次  推薦: 16   [收藏]  

  Objective-C是一種簡單的計算機語言,設計為可以支持真正的面向對象編程。Objective-C通過提供類定義,方法以及屬性的語法,還有其他可以提高類的動態擴展能力的結構等,擴展了標準的ANSI C語言。類的語法和設計主要是基于Smalltalk,最早的面向對象編程語言之一。

  如果你以前使用過其他面向對象編程語言,那么下面的信息可以幫助你學習Objective-C的基本語法。許多傳統的面向對象概念,例如封裝,繼承以及多態,在Objective-C中都有所體現。這里有一些重要的不同,但是這些不同在這文章會表現出來,而且如果你需要還有更多詳細的信息存在。

  如果你從來沒有使用任何編程語言編過程序,那么你至少需要在開始之前,對相關概念進行一些基礎的了解。對象的使用和對象對象架構是iPhone程序設計的基礎,理解他們如何交互對創建你的程序非常重要。想了解面向對象概念的,請參看使用Objective-C進行面向對象編程。此外,參看Cocoa基礎指南可以獲得Cocoa中的面向對象設計模式的信息。

  Objective-C: C的超集

  Objective-C是ANSI版本C編程語言的超集,支持C的基本語法。在C代碼中,你定義頭文件和源代碼文件,從代碼實現細節分離公共聲明。Objective-C頭文件使用的文件名列在表1中。  

  表1 Objective-C代碼的文件擴展名

擴展名 內容類型
.h 頭文件。頭文件包含類,類型,函數和常數的聲明。
.m 源代碼文件。這是典型的源代碼文件擴展名,可以包含Objective-C和C代碼。
.mm 源代碼文件。帶有這種擴展名的源代碼文件,除了可以包含Objective-C和C代碼以外還可以包含C++代碼。僅在你的Objective-C代碼中確實需要使用C++類或者特性的時候才用這種擴展名。

  當你需要在源代碼中包含頭文件的時候,你可以使用標準的#include編譯選項,但是Objective-C提供了更好的方法。#import選項和#include選項完全相同,只是它可以確保相同的文件只會被包含一次。Objective-C的例子和文檔都傾向于使用#import,你的代碼也應該是這樣的。

  字符串

  作為C語言的超集,Objective-C支持C語言字符串方面的約定。也就是說,單個字符被單引號包括,字符串被雙引號包括。然而,大多數Objective-C通常不使用C語言風格的字符串。反之,大多數框架把字符串傳遞給NSString對象。NSString類提供了字符串的類包裝,包含了所有你期望的優點,包括對保存任意長度字符串的內建內存管理機制,支持Unicode,printf風格的格式化工具,等等。因為這種字符串使用的非常頻繁,Objective-C提供了一個助記符可以方便地從常量值創建NSString對象。要使用這個助記符,你需要做的全部事情,是在普通的雙引號字符串前放置一個@符號,如下面的例子所示:

 
NSString* myString = @"My String\n";
NSString
* anotherString = [NSString stringWithFormat:@"%d %s", 1, @"String"];

// 從一個C語言字符串創建Objective-C字符串
NSString* fromCString = [NSString stringWithCString:"A C string" 
encoding:NSASCIIStringEncoding];

  類

  如同所有其他的面向對象語言,類是Objective-C用來封裝數據,以及操作數據的行為的基礎結構。對象就是類的運行期間實例,它包含了類聲明的實例變量自己的內存拷貝,以及類成員的指針。Objective-C的類規格說明包含了兩個部分:接口和實現。接口部分包含了類聲明和實例變量的定義,以及類相關的方法。實現部分包含了類方法的實際代碼。圖1展現了聲明一個叫做MyClass的類的語法,這個類繼承自NSObject基礎類。類聲明總是由@interface編譯選項開始,由@end編譯選項結束。類名之后的(用冒號分隔的)是父類的名字。類的實例(或者成員)變量聲明在被大括號包含的代碼塊中。實例變量塊后面就是類聲明的方法的列表。每個實例變量和方法聲明都以分號結尾。

圖1 類聲明

  列表1展現了前面例子中MyClass類的實現。類同與類聲明,類實現的位置也由兩個編譯選項確定,@implementation和@end。這些選項給編譯器提供了要將方法和對應類聯系起來,所需的范圍信息。因此方法的定義和接口中對應的聲明是匹配的,只是多了個代碼塊而已。

  列表1 類實現

@implementation MyClass
    
- (id)initWithString:(NSString *) aName
{
    if (self = [super init]) {
        count count = 0;
        data = nil;
        name = [aName copy];
        return self;
    }
}
  
+ (MyClass *)createMyClassWithString: (NSString *) aName
{
    return [[[self alloc] initWithString:aName] autorelease];
}
@end

  注意: 雖然前面的類只聲明了方法,但是類可以聲明屬性。

  當用變量保存對象的時候,始終應該使用指針類型。Objective-C對變量包含的對象支持強弱兩種類型。強類型指針的變量類型聲明包含了類名。弱類型指針使用id作為對象的類型。弱類型指針常用于類的集合,在集合中對象精確的類型可以是未知的。如果你用過強類型語言,你也許覺得使用弱類型變量可能會帶來問題,但是他們實際上給了Objective-C程序巨大的靈活性,而且使它更強大。

  下面的例子里,展示了MyClass類的強類型和弱類型聲明變量:

 
MyClass* myObject1; // Strong typing
id myObject2; // Weak typing

  方法

  Objective-C中的類可以聲明兩種類型的方法:實例方法和類方法。實例方法就是一個方法,它在類的一個具體實例的范圍內執行。也就是說,在你調用一個實例方法前,你必須首先創建類的一個實例。而類方法,比較起來,也就是說,不需要你創建一個實例。

  方法聲明包括方法類型標識符,返回值類型,一個或多個方法標識關鍵字,參數類型和名信息。圖2展示insertObject:atIndex:實例方法的聲明。聲明由一個減號(-)開始,這表明這是一個實例方法。方法實際的名字(insertObject:atIndex:)是所有方法標識關鍵的級聯,包含了冒號。冒號表明了參數的出現。如果方法沒有參數,你可以省略第一個(也是唯一的)方法標識關鍵字后面的冒號。本例中,這個方法有兩個參數。

圖2 方法聲明語法

  當你想調用一個方法,你傳遞消息到對應的對象。這里消息就是方法標識符,以及傳遞給方法的參數信息。發送給對象的所有消息都會動態分發,這樣有利于實現Objective-C類的多態行為。也就是說,如果子類定義了跟父類的具有相同標識符的方法,那么子類首先收到消息,然后可以有選擇的把消息轉發(也可以不轉發)給他的父類。

  消息被中括號( [ 和 ] )包括。中括號中間,接收消息的對象在左邊,消息(包括消息需要的任何參數)在右邊。例如,給myArray變量傳遞消息insertObject:atIndex:消息,你需要使用如下的語法:

[myArray insertObject:anObj atIndex:0];

  為了避免聲明過多的本地變量保存臨時結果,Objective-C允許你使用嵌套消息。每個嵌套消息的返回值可以作為其他消息的參數或者目標。例如,你可以用任何獲取這種值的消息來代替前面例子里面的任何變量。所以,如果你有另外一個對象叫做myAppObject擁有方法,可以訪問數組對象,以及插入對象到一個數組,你可以把前面的例子寫成如下的樣子:

[[myAppObject getArray] insertObject:[myAppObject getObjectToInsert] atIndex:0];

  雖然前面的例子都是傳遞消息給某個類的實例,但是你也可以傳遞消息給類本身。當給類發消息,你指定的方法必須被定義為類方法,而不是實例方法。你可以認為類方法跟C++類里面的靜態成員有點像(但是不是完全相同的)。

  類方法的典型用途是用做創建新的類實例的工廠方法,或者是訪問類相關的共享信息的途徑。類方法聲明的語法跟實例方法的幾乎完全一樣,只有一點小差別。與實例方法使用減號作為方法類型標識符不同,類方法使用加號( + )。

  下面的例子演示了一個類方法如何作為類的工廠方法。在這里,arrayWithCapacity是NSMutableArray類的類方法,為類的新實例分配內容并初始化,然后返回給你。

 
NSMutableArray* myArray = nil; // nil is essentially the same as NULL

// Create a new array and assign it to the myArray variable.
myArray = [NSMutableArray arrayWithCapacity:0];

  屬性

  屬性是用來代替聲明存取方法的便捷方式。屬性不會在你的類聲明中創建一個新的實例變量。他們僅僅是定義方法訪問已有的實例變量的速記方式而已。暴露實例變量的類,可以使用屬性記號代替getter和setter語法。類還可以使用屬性暴露一些“虛擬”的實例變量,他們是部分數據動態計算的結果,而不是確實保存在實例變量內的。

  實際上可以說,屬性節約了你必須要寫的大量多余的代碼。因為大多數存取方法都是用類似的方式實現的,屬性避免了為類暴露的每個實例變量提供不同的getter和setter的需求。取而代之的是,你用屬性聲明指定你希望的行為,然后在編譯期間合成基于聲明的實際的getter和setter方法。

  屬性聲明應該放在類接口的方法聲明那里。基本的定義使用@property編譯選項,緊跟著類型信息和屬性的名字。你還可以用定制選項對屬性進行配置,這決定了存取方法的行為。下面的例子展示了一些簡單的屬性聲明:

@property BOOL flag;
@property (copy) NSString* nameObject; // Copy the object during assignment.
@property (readonly) UIView* rootView; // Create only a getter method.

  使用屬性另外的好處就是你可以在代碼中訪問他們的時候,使用點語法,如下面的例子所示:

 
myObject.flag = YES;
CGRect viewFrame
= myObject.rootView.frame;

  雖然前面例子里面的對象和屬性名是故意這么取的,他們還是展現了屬性的靈活性。點語法實際上隱藏了對應的方法調用。每個可讀的屬性由一個與屬性同名的方法支持。每個可寫屬性由一個叫做“set屬性名”的額外方法來支持,屬性名的第一個字母要大寫。(這些方法是屬性的實際實現方式,也是你可以聲明一個沒有任何實例變量支持的屬性聲明的原因。)如果用方法來代替前面代碼中的屬性,你就要下下面的代碼:

 
[myObject setFlag:YES];
CGRect viewFrame
= [[myObject rootView] frame];

  協議和代理

  協議聲明了可以被任何類實現的方法。協議不是那些類本身。他們僅是定義一個接口,其他的對象去負責實現。你實現了協議里面的方法,就叫做符合協議。

  在iPhone OS中協議常用來實現委托對象。委托對象就是一個對象以其他的對象的模式行事。了解協議,委托和對象最好的辦法就是看一個例子。

  UIApplication類實現了一個程序需要的行為。如果想接收程序當前狀態的簡單消息,并不需要強制你創建UIApplication的一個子類,反之UIApplication類通過調用委托對象的指定方法來分發這些通知消息。實現UIApplicationDelegate方法的對象都可以接受這樣的通知,并進行響應的反應。

  協議的聲明跟類接口的聲明很像,只是協議沒有父類,而且他們不會定義任何實例變量。下面的例子展示了一個有一個方法的協議聲明:

 
@protocol MyProtocol
- (void)myProtocolMethod;
@end

  在大多數委托協議情況下,使用某種協議僅僅是簡單的實現協議定義的方法而已。 有些協議要求你明確的表明你支持這種協議,協議可以指定必須或者可選的方法。在你深入開發的過程中,你應該花點時間學習協議以及他們的用途。

  更多的信息

  前面的信息是為了讓你對Objective-C語言的基礎所有了解。本文提到的語言特性,你可以在閱讀完整文檔的時候找到。但是這個語言不僅僅有這些特性,所以最好請仔細閱讀文檔Objective-C 2.0編程語言

16
1
 
標簽:Objective-C iOS
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()