標籤:
當你著手為你的應用編寫代碼的時候,你會發現有許多可供使用的Objective-C的架構類,其中尤其重要的就是基礎架構類,它為平台所有的應用提供基礎服務。基礎架構類中包括了表示字串和數字等基礎資料型別 (Elementary Data Type)的值類(value classes),也有用來儲存其他對象的集合類(collection classes)。你將會依賴值類和集合類為你的ToDoList app編寫大量代碼。
值對象(Value Objects) Foundation架構提供了產生字串、位元據、日期和時間、數字以及其他值對象的類。 值對象封裝了C語言中的基礎資料型別 (Elementary Data Type),並提供針對相應資料類型操作的方法。在程式調用中,你會經常遇到將值對象作為參數或傳回值的方法和函數。架構中的不同部分,乃至不同架構之間都可以通過值對象類傳遞資料。 Foundation架構中值對象的例子:• NSString and NSMutableString • NSData and NSMutableData • NSDate • NSNumber • NSValue 因為值對象代表的是標量值,你可以在集合類和其他任何需要的類中使用它們。相比它封裝的基中繼資料,值對象可以讓你更簡單高效地操作它封裝的值。以NSString類為例,它包含了尋找替換子字串、把字串寫入檔案或URL、利用字串構建檔案系統路徑等方法。 你可以用基中繼資料建立一個值對象(如果有必要的話,將其作為參數傳遞給某一方法),之後就可以通過該對象來訪問被封裝的資料。下面以NSNumber類來示範說明以上建立值對象的方法。
- int n = 5; // Value assigned to primitive type
- NSNumber *numberObject = [NSNumber numberWithInt:n]; // Value object created from primitive type
- int y = [numberObject intValue]; // Encapsulated value obtained from value object (y == n)
大多數值類通過聲明初始化器和類Factory 方法來建立它們的執行個體。類Factory 方法可以完成執行個體的分配和初始化,返回一個被建立的對象。例如,NSString類聲明了一個string類方法,可以分配並初始化該類的一個新執行個體,並作為傳回值返回給你的代碼使用。
- NSString *string = [NSString string];
除了建立值對象,並讓你訪問它們封裝的值,多數值類都提供了諸如對象比較之類的簡單操作方法。
字串Objective-C支援同C語言一樣的慣例來指定字串:通過單引號表示單個字元,雙引號表示字串,但是Objective-C架構一般不使用C字串,它們通常使用NSString對象。 NSString類提供了一個字串的封裝,具有以下優勢:內建記憶體管理功能可以儲存任意長度的字串、支援不同的字元編碼(尤其是Unicode)以及字元格式設定化的方法。因為你常常會用到這樣的字串,所以Objective-C提供了一種從常量值建立NSString對象的簡便方法。想要使用該常量,可在字串的雙引號前面加一個@符號即可,如下例所示。
- // Create the string "My String" plus carriage return.
- NSString *myString = @"My String\n";
- // Create the formatted string "1 String".
- NSString *anotherString = [NSString stringWithFormat:@"%d %@", 1, @"String"];
- // Create an Objective-C string from a C string.
- NSString *fromCString = [NSString stringWithCString:"A C string" encoding:NSUTF8StringEncoding];
數字Objective-C為建立NSNumber對象的提供了簡化符號,除去了調用初始化器或者類Factory 方法建立這些對象的需要。只需簡單地在數值前面加@符號即可,你還可以在數值之後加一個類型指示符。比如,想要建立一個封裝了整數值和雙精確度值的NSNumber對象,你需要編寫如下代碼:
- NSNumber *myIntValue = @32;
- NSNumber *myDoubleValue = @3.22346432;
你甚至可以使用NSNumber常量來建立封裝布爾類型和字元類型的對象,如下所示:
- NSNumber *myBoolValue = @YES;
- NSNumber *myCharValue = @‘V‘;
你可以通過U、L、LL、和F尾碼來建立分別代表無符號整型、長整型、超長整型和浮點類型的NSNumber對象。如下程式碼範例建立了一個封裝了浮點實值型別的NSNUmber對象:
- NSNumber *myFloatValue = @3.2F;
集合對象 Objective-C中的大部分集合對象都是NSArray、NSSet和NSDictionary這些基本集合類的執行個體。這些類用來管理群組對象,所以你添加到集合中的執行個體必須為一個Objective-C類。如果你需要添加標量數值,你必須建立一個合適的NSNumber或NSValue執行個體來代表它。 在集合被銷毀前,集合中儲存的成員對象不能被銷毀。這是因為集合類採用強引用來維護它的成員對象。除了跟蹤維護它對象外,集合類還提供枚舉、訪問特定對象、判斷某一對象是否在集合內等功能。 NSArray, NSSet和 NSDictionary類的內容在集合建立時即被初始化,之後在使用中不能再被改變,這種類叫不可變類。每一個集合類都有一個可變的子類允許你隨意添加刪除成員對象。不同集合類組織它們成員對象的方式是不同的:• NSArray和NSMutableArray—儲存有序對象的數組。你可以通過在數組中指定位置來訪問一個成員對象。數組中第一個元素的索引為0。• NSSet和NSMutebleSet—儲存無序對象的集合。每個元素在集合中具有唯一性。你只能通過測試或篩選的方法來訪問集合中的對象。• NSDictionary和NSMutableDictionary—通過索引值對儲存的一個詞典。鍵是一個獨特的標識符,通常是一個字串,值就是你想要儲存的對象。你可以通過指定鍵來訪問該對象。
數組數組(NSArray)用來表示一組有序對象,唯一的要求是每個對象必須是一個Objective-C對象,至於每個對象是不是同一個類的執行個體沒有要求。 為了維護數組的有序性,元素的索引從0開始,如所示:建立數組與本章前面介紹的值類相同,你可以通過分配和初始化、Factory 方法或者常數陣列來建立一個數組。根據對象個數的不同,有很多初始化和Factory 方法可供使用:
- + (id)arrayWithObject:(id)anObject;
- + (id)arrayWithObjects:(id)firstObject, ...;
- - (id)initWithObjects:(id)firstObject, ...;
由於arrayWithObjects:和initWithObjects:方法都是可變參數長度並以nil結束,初始化如下代碼所示:
- NSArray *someArray =
- [NSArray arrayWithObjects:someObject, someString, someNumber, someValue, nil];
上例建立了一個與之前類似的數組,其中第一個對象someObject的索引值是0,最後一個對象someValue的索引值是3。 如果中間某一個值是nil,數組可能會被截斷。
- id firstObject = @"someString";
- id secondObject = nil;
- id thirdObject = @"anotherString";
- NSArray *someArray =
- [NSArray arrayWithObjects:firstObject, secondObject, thirdObject, nil];
本例中,someArray只包含firstObject,因為secondObject的值是nil,因此被當作數組的結束符。 可以使用如下簡便的文法來建立一個常數陣列:
- NSArray *someArray = @[firstObject, secondObject, thirdObject];
當使用這個文法是,不要用nil來結束對象列表,實際上,nil是一個不存在的值。例如,你在執行以下代碼時會得到一個運行異常:
- id firstObject = @"someString";
- id secondObject = nil;
- NSArray *someArray = @[firstObject, secondObject];
- // exception: "attempt to insert nil object"
查詢數組對象建立完數組之後,你可以查詢其中個的資訊,比如它包含多少對象,或它是否包含某一給定對象。
- NSUInteger numberOfItems = [someArray count];
-
- if ([someArray containsObject:someString]) {
- ...
- }
你還可以通過一個給定的索引來查詢數組的項目,如果嘗試請求一個不存在的索引,那麼運行時你將得到一個越界異常。為了防止異常,在使用前請首先檢查數組中項目的個數。
- if ([someArray count] > 0) {
- NSLog(@"First item is: %@", [someArray objectAtIndex:0]);
- }
本例子檢查了對象個數是否大於零,如果是,Foundation架構函數NSLog輸出一個數組中第一個元素的說明,它的索引為0。 另外一種方法是使用objecAtIndex,你還可以像C語言那樣,使用方括弧文法查詢數組元素,上一個例子還可以寫成這樣:
- if ([someArray count] > 0) {
- NSLog(@"First item is: %@", someArray[0]);
- }
數組對象排序 NSArray類為對象排序提供了一系列方法。因為NSArray是不可變的,因此這些方法會返回一個包含排序後對象的新數組。 例如,你可以通過對每個字串調用compare:方法來排序字串數組:
- NSArray *unsortedStrings = @[@"gammaString", @"alphaString", @"betaString"];
- NSArray *sortedStrings =
- [unsortedStrings sortedArrayUsingSelector:@selector(compare:)];
可變性儘管NSArray類本身是不可變的,但是它可以包含可變對象,例如,你可以在不可變數組中添加一個可變字串,如下所示:
- NSMutableString *mutableString = [NSMutableString stringWithString:@"Hello"];
- NSArray *immutableArray = @[mutableString];
於是你可以隨意改變字串的內容。
- if ([immutableArray count] > 0) {
- id string = immutableArray[0];
- if ([string isKindOfClass:[NSMutableString class]]) {
- [string appendString:@" World!"];
- }
- }
如果想在數組建立後添加或刪除數組中的對象,你可以使用NSMutableArray,該類添加了一系列方法來添加刪除、替換一個或多個對象。
- NSMutableArray *mutableArray = [NSMutableArray array];
- [mutableArray addObject:@"gamma"];
- [mutableArray addObject:@"alpha"];
- [mutableArray addObject:@"beta"];
-
- [mutableArray replaceObjectAtIndex:0 withObject:@"epsilon"];
本樣本建立了一個由對象@"epsilon", @"alpha"和 @"beta"組成的數組。對於可變數組,你可以在不產生新數組的情況下對數組進行排序,如下所示:
- [mutableArray sortUsingSelector:@selector(caseInsensitiveCompare:)];
本例中,數組元素按升序排列,不區分大小寫。
集集對象與數組類似,但是它包含的是無序互異對象。由於集是無序的,因此在測試成員對象時效能比數組要好。集是不可變的,因此它的內容必須在建立時指定。
- NSSet *simpleSet =
- [NSSet setWithObjects:@"Hello, World!", @42, aValue, anObject, nil];
同NSArray類一樣,initWithObjects:和setWithObjects:方法是可變長度的參數,必須以nil結束。NSSet的可變子類是NSMutableSet。 每個對象集只儲存一次,即使你不止一次添加一個對象。
- NSNumber *number = @42;
- NSSet *numberSet =
- [NSSet setWithObjects:number, number, number, number, nil];
- // numberSet only contains one object
詞典與簡單的維護一個有序或無序的集合對象不同,詞典(NSDictionary)使用給定索引值對存取對象,它可以被用於檢索。通常使用字串對象作為字典的鍵。儘管你可以使用其他對象作為鍵,但是請記住每個鍵是被複製到字典中的,因此該對象必須支援NSCopying方法。然而,如果你想要使用索引值對編碼,你必須使用string key作為詞典對象(詳情請參見Key-Value Coding Programming Guide)。 建立詞典你可以使用alloc和初始化,或類的Factory 方法來建立詞典,如下所示:
- NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
- someObject, @"anObject",
- @"Hello, World!", @"helloString",
- @42, @"magicNumber",
- someValue, @"aValue",
- nil];
對於 dictionaryWithObjectsAndKeys: 和 initWithObjectsAndKeys: 方法,每個對象必須在鍵前面聲明,並以nil結束。 Objective-C為詞典常量建立提供了簡便文法:
- NSDictionary *dictionary = @{
- @"anObject" : someObject,
- @"helloString" : @"Hello, World!",
- @"magicNumber" : @42,
- @"aValue" : someValue
- };
對於字典常量,鍵在對象前指定,並且列表對象和鍵無需以nil結束。 查詢詞典建立詞典之後,你可以查詢鍵對應的對象,如下所示:
- NSNumber *storedNumber = [dictionary objectForKey:@"magicNumber"];
如果對象未找到, objectForKey: 方法會返回 nil. 除了objectForKey:方法,你還可以使用如下方法進行查詢:
- NSNumber *storedNumber = dictionary[@"magicNumber"];
可變性如果你需要在詞典建立後添加或者刪除內容,請使用NSMutableDictionary 類。
- [dictionary setObject:@"another string" forKey:@"secondString"];
- [dictionary removeObjectForKey:@"anObject"];
使用 NSNull表示nil你不能將nil添加到本節描述的集合類中,因為nil在Objective-C 中代表“不存在的對象”,如果你需要在集合中表示一個不存在的對象,請使用NSNull類。
- NSArray *array = @[ @"string", @42, [NSNull null] ];
在NSNull中,null方法總是返回同一個執行個體,具有這樣行為的類被稱為“骨架類”( singleton classes)。你可以使用以下方法檢查一個對象是否等於NSNull:
- for (id object in array) {
- if (object == [NSNull null]) {
- NSLog(@"Found a null object");
- }
- }
儘管Foundation架構套件含的功能比此處描述的要多很多,但你不需要現在就掌握其每一個細節。如果你想要瞭解更多Foundation架構知識,請參看Foundation Framework Reference。目前你已掌握足夠的資訊來繼續實現ToDoList這個應用,為了實現它你需要寫一個自訂資料類。
ios 對象的集合類(collection classes)