鍍金池/ 教程/ iOS/ 編寫自定類
查找信息
使用設(shè)計模式
設(shè)計用戶界面
應(yīng)用程序開發(fā)過程
iOS 技術(shù)
接下來做什么
串聯(lián)圖
處理 Foundation
編寫自定類
整合數(shù)據(jù)
基礎(chǔ)
設(shè)置
添加數(shù)據(jù)
定義交互

編寫自定類

開發(fā) iOS 應(yīng)用程序時,很多情況下都需要編寫自定類。當(dāng)您需要將自定行為與數(shù)據(jù)打包在一起時,自定類非常有用。在自定類中,可以定義您自己的行為來儲存、操控和顯示數(shù)據(jù)。

例如,iOS 的“時鐘”應(yīng)用程序中的“世界時鐘”標(biāo)簽。比起標(biāo)準表格視圖單元格,此表格視圖中的單元格需要顯示更多內(nèi)容。這是實現(xiàn)子類的絕好機會,可以擴展 UITableViewCell 的行為,從而在給定的表格視圖單元格中顯示更多自定數(shù)據(jù)。如果要設(shè)計此自定類,您可能要為標(biāo)簽添加 Outlet,使信息前顯示小時數(shù);還要添加圖像視圖,使單元格的右側(cè)顯示自定時鐘。

http://wiki.jikexueyuan.com/project/ios-developer-library/images/custom_class_2x.png" alt="" />

本章會告訴您需要了解哪些 Objective-C 語法和類結(jié)構(gòu),才能實現(xiàn) ToDoList 應(yīng)用程序的行為。還討論了 XYZToDoItem 的設(shè)計,該自定類將表示待辦事項列表上的單個項目。在第三個教程中,您將真正實現(xiàn)該類,并將它添加到您的應(yīng)用程序中。

聲明并實現(xiàn)類

在 Objective-C 中,類的說明需要兩個不同的部分:接口和實現(xiàn)。接口準確指定了一個給定類型的對象,如何專用于其他對象。換句話說,它定義了類的實例與外部世界之間的公共接口。這個實現(xiàn)包括的可執(zhí)行代碼,涵蓋了接口中聲明的每個方法。

對象的設(shè)計,應(yīng)當(dāng)隱藏其內(nèi)部實現(xiàn)的細節(jié)。在 Objective-C 中,接口和實現(xiàn)通常放在單獨的文件中,這樣您只需要將接口設(shè)定為公共屬性。和 C 代碼一樣,您需要定義頭文件和源代碼文件,將公共聲明與代碼的實現(xiàn)細節(jié)分開。接口文件具有 .h 擴展名,實現(xiàn)文件具有 .m 擴展名。(您將在“教程:添加數(shù)據(jù)”中為 XYZToDoItem 類真正創(chuàng)建這些文件;眼下我們只需跟著文稿來,因為所有內(nèi)容都將講到。)

接口

Objective-C 語法經(jīng)常采用以下方式來聲明類接口:

@interface XYZToDoItem : NSObject

@end

該示例聲明了名為 XYZToDoItem 的類,它繼承自 NSObject。

公共屬性和行為在 @interface 聲明內(nèi)部定義。在此示例中,除了超類外,沒有指定任何內(nèi)容,所以 XYZToDoItem 實例唯一可用的行為繼承自 NSObject。所有對象都要有一個最基本的行為,因此在默認情況下,它們必須繼承自 NSObject(或它的一個子類)。

實現(xiàn)

Objective-C 語法經(jīng)常采用以下方式來聲明類實現(xiàn):

#import "XYZToDoItem.h"

@implementation XYZToDoItem

@end

如果您在類接口中聲明了任何方法,那么需要在此文件中實現(xiàn)它們。

儲存對象的數(shù)據(jù)的屬性

考慮待辦事項需要保存的信息。您可能需要知道事項的名稱,創(chuàng)建時間,以及是否已經(jīng)完成。在自定 XYZToDoItem 類中,此信息儲存在屬性中。

這些屬性的聲明在接口文件 (XYZToDoItem.h) 內(nèi)部。如下所示:

@interface XYZToDoItem : NSObject

@property NSString *itemName;
@property BOOL completed;
@property NSDate *creationDate;

@end

在此示例中,XYZToDoItem 類聲明了三個公共屬性。這些屬性完全可供公開訪問。在公開訪問的情況下,其他對象可以同時讀取和更改這些屬性的值。

您可能想要聲明某個屬性不能被更改(也就是說,只能讀?。?。指明一個屬性是否只讀(相對于其他屬性),需要在 Objective-C 的屬性聲明中包括屬性的特性。例如,如果您不想 XYZToDoItem 的創(chuàng)建日期被改變,可能需要將 XYZToDoItem 類接口更新為這樣:

@interface XYZToDoItem : NSObject

@property NSString *itemName;
@property BOOL completed;
@property (readonly) NSDate *creationDate;

@end

屬性可以是私有的或公共的。有時讓屬性私有是合理的選擇,這樣其他類就不能查看或訪問它。例如,如果您想要跟蹤的標(biāo)記是項目完成的日期屬性,并且不想讓其他類訪問此信息,請將此屬性設(shè)為私有,方法是將它放在實現(xiàn)文件 (XYZToDoItem.m) 頂部的類擴展中。

#import "XYZToDoItem.h"

@interface XYZToDoItem ()
@property NSDate *completionDate;
@end

@implementation XYZToDoItem

@end

您可以使用 getter 和 setter 來訪問屬性。getter 返回屬性的值,setter 更改屬性的值。訪問 getter 和 setter 的常見語法簡寫是 dot notation(點表達式)。對于具有讀寫訪問權(quán)限的屬性,您可以使用點表達式來獲取和設(shè)定屬性的值。如果您有 XYZToDoItem 類的一個對象 toDoItem,可以執(zhí)行以下操作:

toDoItem.itemName = @"Buy milk";                 //Sets the value of itemName
NSString *selectedItemName = toDoItem.itemName;  //Gets the value of itemName

方法用來定義對象的行為

方法用來定義對象能做些什么。方法是您定義的一段代碼,用來執(zhí)行類中的任務(wù)或子程序。它可以訪問類中儲存的數(shù)據(jù),并使用該信息來執(zhí)行一些操作。

例如,要讓待辦事項 (XYZToDoItem) 能夠被標(biāo)記為已完成,您可以將 markAsCompleted 方法添加到類接口。稍后,您將在類實現(xiàn)中實現(xiàn)該方法的行為,正如“實現(xiàn)方法”中所述。

@interface XYZToDoItem : NSObject

@property NSString *itemName;
@property BOOL completed;
@property (readonly) NSDate *creationDate;
- (void)markAsCompleted;

@end

方法名稱前面的減號 (-) 指示它是一個實例方法,可以用該類的對象調(diào)用。減號將它與類方法區(qū)分開來,類方法用加號 (+) 來表示。類方法可通過類本身來調(diào)用。類方法的一個常見示例是類工廠方法,您已經(jīng)在“處理 Foundation”中學(xué)習(xí)過。您也可以使用類方法來訪問與類相關(guān)的一些共享信息。

在聲明的開始,用圓括號括住 void 關(guān)鍵詞,表示方法不會返回值。這種情況下,markAsCompleted 方法沒有任何參數(shù)。“方法參數(shù)”中會講述有關(guān)參數(shù)的更多信息。

方法參數(shù)

在聲明方法時加上參數(shù),可在調(diào)用方法時傳遞一些信息。

例如,您可以根據(jù)之前的代碼片段修改 markAsCompleted 方法,讓其帶單個參數(shù),借此確定項目是否標(biāo)記為完成或未完成。用這種方式,您可以切換項目的完成狀態(tài),而不只是將它設(shè)為完成。

@interface XYZToDoItem : NSObject

@property NSString *itemName;
@property BOOL completed;
@property (readonly) NSDate *creationDate;
- (void)markAsCompleted:(BOOL)isComplete;

@end

現(xiàn)在,您的方法采用了一個參數(shù) isComplete,其類型為 BOOL。

通過名稱引用帶一個參數(shù)的方法時,冒號將作為方法名稱的一部分,所以更新后的方法名稱是 markAsCompleted:。如果方法有多個參數(shù),那么它會被分解,并插入?yún)?shù)名稱。如果要將另一個參數(shù)添加到此方法,其聲明將會是這樣的:

- (void)markAsCompleted:(BOOL)isComplete onDate:(NSDate *)date;

在這里,方法的名稱寫為 markAsCompleted:onDate:。實現(xiàn)時會使用名稱 isComplete 和 date(會將這些名稱當(dāng)作變量),來訪問方法被調(diào)用時所提供的值。

實現(xiàn)方法

方法實現(xiàn)使用大括號來包括相關(guān)代碼。方法的名稱必須與接口文件中的對應(yīng)方法相同,并且參數(shù)和返回類型必須完全匹配。

這是添加到 XYZToDoItem 類接口的 markAsCompleted: 方法的簡單實現(xiàn):

@implementation XYZToDoItem
- (void)markAsCompleted:(BOOL)isComplete {
    self.completed = isComplete;
}
@end

與屬性一樣,方法也可以是私有的或公共的。公共方法在公共接口中聲明,因此可以被其他對象查看和調(diào)用。它們的相應(yīng)實現(xiàn)存在于實現(xiàn)文件中,其他對象看不到。私有方法僅有一個實現(xiàn),并與類相同,這意味著只可以在類實現(xiàn)中調(diào)用它們。這是一個強大的機制,可將內(nèi)部行為添加到類而不允許其他對象進行訪問。

例如,假設(shè)您想要讓待辦事項的 completionDate 保持更新。當(dāng)待辦事項被標(biāo)記為完成,就將 completionDate 設(shè)定為當(dāng)前日期。當(dāng)它被標(biāo)記為未完成,就將 completionDate 設(shè)定為 nil,因為它尚未完成。由于更新待辦事項的 completionDate 是自包含任務(wù),所以最好的做法是為其編寫專屬方法。但是,應(yīng)當(dāng)確定其他對象不能調(diào)用此方法。否則,其他對象可以隨時將待辦事項的 completionDate 設(shè)定為任何內(nèi)容。因此,請將此方法設(shè)為私有。

現(xiàn)在,更新 XYZToDoItem 的實現(xiàn)來包括私有方法 setCompletionDate,該方法將會在 markAsCompleted: 內(nèi)部調(diào)用,以便在待辦事項被標(biāo)記為已完成或未完成時,更新待辦事項的 completionDate。請注意,您不會添加任何內(nèi)容到接口文件,因為不想其他對象看到此方法。

@implementation XYZToDoItem
- (void)markAsCompleted:(BOOL)isComplete {
    self.completed = isComplete;
    [self setCompletionDate];
}
- (void)setCompletionDate {
    if (self.completed) {
        self.completionDate = [NSDate date];
    } else {
        self.completionDate = nil;
    }
}
@end

現(xiàn)在,您已經(jīng)使用 XYZToDoItem 類定義了待辦事項列表的基本實現(xiàn)。XYZToDoItem 以屬性的形式儲存自身相關(guān)的信息——名稱、創(chuàng)建日期和完成狀態(tài),并且會使用方法定義行為——被標(biāo)記為已完成或未完成。這是您在下一個教程中實現(xiàn) ToDoList 應(yīng)用程序所需的功能擴展。不過,您隨時可以嘗試將自己的屬性和方法添加到類,將新的行為集成到您的應(yīng)用程序中。

上一篇:查找信息下一篇:添加數(shù)據(jù)