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

處理 Foundation

開始編寫應(yīng)用程序的代碼時(shí),可以利用大量的 Objective-C 框架。其中,為所有應(yīng)用程序提供基本服務(wù)的 Foundation 框架尤為重要。Foundation 框架包括表示基本數(shù)據(jù)類型的值類(如字符串和數(shù)字)以及用于儲存其他對象的集 (collection) 類。ToDoList 應(yīng)用程序中的大量代碼都可以依靠值類和集類來編寫。

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

值對象

Foundation 框架提供了為字符串、二進(jìn)制數(shù)據(jù)、日期與時(shí)間、數(shù)字以及其他值產(chǎn)生值對象的類。

值對象是指封裝了基本值(屬于 C 數(shù)據(jù)類型)且提供與該值相關(guān)的服務(wù)的對象。您會頻繁遇到值對象,作為應(yīng)用程序調(diào)用的方法和函數(shù)的參數(shù)和返回值??蚣艿牟煌糠?,甚至不同的框架都可以通過傳遞值對象來交換數(shù)據(jù)。

以下是 Foundation 框架中值對象的幾個(gè)示例:

NSString 和 NSMutableString
NSData 和 NSMutableData
NSDate
NSNumber
NSValue

由于值對象表示標(biāo)量值,因此您可以在集 (collection) 中使用,也可以在任何需要對象的地方使用。基于值對象所封裝的基本類型,它們有一項(xiàng)天然優(yōu)勢:可讓您采用簡單而高效的方式對封裝的值執(zhí)行某些操作。例如,NSString 類具有用于搜索和替換子字符串、將字符串寫入文件或(首選)URL 以及構(gòu)建文件系統(tǒng)路徑的方法。

您可以從基本類型的數(shù)據(jù)創(chuàng)建值對象(然后在方法參數(shù)中傳遞它)。稍后,您可通過代碼從該對象訪問被封裝的數(shù)據(jù)。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)

大多數(shù)值類會通過聲明初始化程序和類工廠方法來創(chuàng)建其實(shí)例。類工廠方法由類實(shí)施,作為提供給客戶的簡單方法;它將分配和初始化結(jié)合為一個(gè)步驟,并返回已創(chuàng)建的對象。例如,NSString 類可聲明 string 類方法,以便分配和初始化類的新實(shí)例,并將其返回到代碼中。

NSString *string = [NSString string];

除創(chuàng)建值對象和讓您訪問其封裝值之外,大多數(shù)值類都提供用于簡單操作(如對象比較)的方法

字符串

Objective-C 指定字符串的約定與 C 相同:單個(gè)字符會使用單引號括起來,而字符串則使用雙引號括起來。但是,Objective-C 框架通常不使用 C 字符串。相反,它們會使用 NSString 對象。

NSString 類為字符串提供了一個(gè)對象包裝器,它具有諸多優(yōu)勢,如內(nèi)置了可用于儲存任意長度字符串的內(nèi)存管理、提供了對各種字符編碼(特別是 Unicode)的支持,以及用于格式化字符串的實(shí)用工具等。因?yàn)槟ǔ褂么祟愖址?,所?Objective-C 提供了速寫記法,即根據(jù)常量值來創(chuàng)建 NSString 對象。要使用此 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];

數(shù)字

Objective-C 提供了創(chuàng)建 NSNumber 對象的速寫記法,從而無需調(diào)用初始化程序或類工廠方法就可以創(chuàng)建此類對象。只需在數(shù)值前面添加 (@) 符號,并選擇一個(gè)添加在其后面的值類型指示。例如,創(chuàng)建封裝整數(shù)值和雙精度值的 NSNumber 對象,可以編寫如下代碼:

NSNumber *myIntValue    = @32;
NSNumber *myDoubleValue = @3.22346432;

您甚至可以使用 NSNumber 字面常量來創(chuàng)建封裝的 Boolean 值和字符值。

NSNumber *myBoolValue = @YES;
NSNumber *myCharValue = @'V';

可以創(chuàng)建 NSNumber 對象,表示無符號整型 (unsigned integers)、長整型 (long integers)、長長整型 (long long integers) 和浮點(diǎn)值 (float values),方法是將字符“U”、“L”、“LL”和“F”分別追加到記號值末尾。例如,創(chuàng)建封裝浮點(diǎn)值的 NSNumber 對象,可以編寫如下代碼:

NSNumber *myFloatValue = @3.2F

集對象

Objective-C 代碼中的大多數(shù)集對象都是一種基礎(chǔ)集類(NSArray、NSSet 和 NSDictionary)的實(shí)例。這些類用于管理對象組,因此要添加到集 (collection) 中的任何項(xiàng)目都必須是 Objective-C 類的實(shí)例。如果要添加標(biāo)量值,就必須先創(chuàng)建合適的 NSNumber 或 NSValue 實(shí)例來表示它。

添加進(jìn)集的任何對象的生命周期都將不短于集。因?yàn)榧悤褂脧?qiáng)引用來跟蹤其內(nèi)容。除了跟蹤其內(nèi)容之外,每個(gè)集類都便于您執(zhí)行特定的任務(wù),如枚舉、訪問特定項(xiàng)目或是找出特殊的對象是否屬于集的一部分。

NSArray、NSSet 和 NSDictionary 類的內(nèi)容在創(chuàng)建時(shí)就應(yīng)設(shè)定。因?yàn)樗鼈儾荒茈S時(shí)間而變化,所以被稱為不可變。每個(gè)類還有一個(gè)可變的子類,允許您隨意添加或移除對象。不同類型的集采用不同的方式組織它們所包含的對象:

  • NSArray 和 NSMutableArray—數(shù)組,包含有序的對象集。通過在數(shù)組中指定對象的位置(即索引)來訪問對象。數(shù)組中首個(gè)元素的索引是 0(零)。
  • NSSet 和 NSMutableSet—集合,儲存無序的對象集,其中每個(gè)對象僅出現(xiàn)一次。一般是將測試或過濾器應(yīng)用到集合中的對象,來訪問這些集合中的對象。
  • NSDictionary 和 NSMutableDictionary—字典,其條目儲存為鍵-值對;鍵是唯一的標(biāo)識符,通常為字符串,而值則是您要儲存的對象。通過指定鍵,您可以訪問該對象。

數(shù)組

數(shù)組 (NSArray) 用于表示有序的對象列表。只要求每個(gè)項(xiàng)目都是 Objective-C 對象;不要求每個(gè)對象都是同一個(gè)類的實(shí)例。

如果要保持?jǐn)?shù)組中的順序,每個(gè)元素都應(yīng)儲存在從 0 開始的索引中。

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

創(chuàng)建數(shù)組

與本章前文所述的值類一樣,您可以通過分配和初始化、類工廠方法或數(shù)組字面常量來創(chuàng)建數(shù)組。

根據(jù)對象數(shù)量的不同,可用的初始化和工廠方法也多種多樣。

+ (id)arrayWithObject:(id)anObject;
+ (id)arrayWithObjects:(id)firstObject, ...;
- (id)initWithObjects:(id)firstObject, ...;

由于 arrayWithObjects: 和 initWithObjects: 方法都采用了以 nil 結(jié)束且數(shù)量可變的參數(shù),所以您必須包括 nil 并將其作為最后一個(gè)值。

NSArray *someArray =
[NSArray arrayWithObjects:someObject, someString, someNumber, someValue, nil];

此示例會創(chuàng)建一個(gè)如上文所示的數(shù)組。第一個(gè)對象 someObject 的數(shù)組索引為 0;最后一個(gè)對象 someValue 的索引則為 3。

如果所提供的其中一個(gè)值為 nil ,則有可能使項(xiàng)目列表意外截?cái)唷?/p>

id firstObject = @"someString";
id secondObject = nil;
id thirdObject = @"anotherString";
NSArray *someArray =
  [NSArray arrayWithObjects:firstObject, secondObject, thirdObject, nil];

在這種情況下,someArray 只會包含 firstObject,因?yàn)?secondObject(即 nil)會被解析為項(xiàng)目列表的末尾。

使用緊湊語法創(chuàng)建數(shù)組字面常量也是有可能的。

NSArray *someArray = @[firstObject, secondObject, thirdObject];

使用此語法時(shí),請勿使用 nil 來結(jié)束對象列表;實(shí)際上,nil 是無效值。例如,如果您嘗試執(zhí)行以下代碼,那么會在運(yùn)行時(shí)中捕獲到一個(gè)異常:

id firstObject = @"someString";
id secondObject = nil;
NSArray *someArray = @[firstObject, secondObject];
// exception: "attempt to insert nil object"

查詢數(shù)組對象

創(chuàng)建數(shù)組后,可以通過查詢來獲得信息,如其中有多少個(gè)對象,或者其中是否包含給定的項(xiàng)目。

NSUInteger numberOfItems = [someArray count];

if ([someArray containsObject:someString]) {
    ...
}

還可以按照給定索引查詢數(shù)組來找到項(xiàng)目。如果請求的索引無效,那么會在運(yùn)行時(shí)中獲得越界異常。為了避免得到異常,應(yīng)始終首先檢查項(xiàng)目的數(shù)量。

if ([someArray count] > 0) {
    NSLog(@"First item is: %@", [someArray objectAtIndex:0]);
}

此示例用于檢查項(xiàng)目的數(shù)量是否大于 0。如果數(shù)量大于 0,F(xiàn)oundation 函數(shù) NSLog 會記錄第一個(gè)項(xiàng)目(索引為 0)的描述。

除了使用 objectAtIndex: 之外,還可以使用下標(biāo)語法來查詢數(shù)組,就像在標(biāo)準(zhǔn)的 C 數(shù)組中訪問值一樣。上一個(gè)示例可被重寫為:

if ([someArray count] > 0) {
    NSLog(@"First item is: %@", someArray[0]);
}

排序數(shù)組對象

NSArray 類提供了多種方法對其收集的對象進(jìn)行排序。由于 NSArray 是不可變的,因此這類方法都會返回新的數(shù)組,并在其中包含排好序的項(xiàng)目。

例如,您可以通過在每個(gè)字符串上調(diào)用 compare:,對字符串?dāng)?shù)組進(jìn)行排序。

NSArray *unsortedStrings = @[@"gammaString", @"alphaString", @"betaString"];
NSArray *sortedStrings =
         [unsortedStrings sortedArrayUsingSelector:@selector(compare:)];

可變性

雖然 NSArray 類本身不可變,但它仍可包含可變對象。例如,如果將可變字符串添加到不可變的數(shù)組,如下所示:

NSMutableString *mutableString = [NSMutableString stringWithString:@"Hello"];
NSArray *immutableArray = @[mutableString];

就可讓您變異該字符串。

if ([immutableArray count] > 0) {
    id string = immutableArray[0];
    if ([string isKindOfClass:[NSMutableString class]]) {
        [string appendString:@" World!"];
    }
}

如果要在初始創(chuàng)建數(shù)組后添加或移除對象,可使用 NSMutableArray,它提供了很多方法來添加、移除或替換一個(gè)或多個(gè)對象。

NSMutableArray *mutableArray = [NSMutableArray array];
[mutableArray addObject:@"gamma"];
[mutableArray addObject:@"alpha"];
[mutableArray addObject:@"beta"];

[mutableArray replaceObjectAtIndex:0 withObject:@"epsilon"];

此示例創(chuàng)建了由對象 @"epsilon"、@"alpha" 和 @"beta" 構(gòu)成的數(shù)組。

還可以對可變數(shù)組進(jìn)行適當(dāng)排序,而無需創(chuàng)建二級數(shù)組。

[mutableArray sortUsingSelector:@selector(caseInsensitiveCompare:)];

在這種情況下,包含在內(nèi)的項(xiàng)目會按升序且不區(qū)分大小寫的順序排列(@"alpha"、@"beta" 和 @"epsilon")。

集合

集合 (NSSet) 對象與數(shù)組類似,只是其中包含的是各種無序的對象。

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

因?yàn)榧喜话樞颍詼y試成員資格時(shí),集合比數(shù)組更快。

由于基礎(chǔ) NSSet 類是不可變的,因此在創(chuàng)建時(shí)就必須指定其內(nèi)容,其中可使用分配和初始化或者類工廠方法。

NSSet *simpleSet =
  [NSSet setWithObjects:@"Hello, World!", @42, aValue, anObject, nil];

如同 NSArray,initWithObjects: 和 setWithObjects: 方法都采用了以 nil 結(jié)束且數(shù)量不固定的參數(shù)。可變的 NSSet 子類名稱是 NSMutableSet。

即使您多次嘗試添加對象,集合也只會儲存對單個(gè)對象的一次引用。

    NSNumber *number = @42;
    NSSet *numberSet =
      [NSSet setWithObjects:number, number, number, number, nil];
    // numberSet only contains one object

字典

與簡單匯集有序或無序的對象集不同,字典 (NSDictionary) 會儲存與給定鍵相關(guān)的對象,用于以后的檢索。

最佳實(shí)踐是將字符串對象用作字典鍵。

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

雖然其他對象也可以用作鍵,但要注意,每個(gè)鍵都會被拷貝以供字典使用,并且必須支持 NSCopying。不過,如果要使用鍵-值編碼,則必須為字典對象使用字符串鍵。若要了解更多信息,請參閱《Key-Value Coding Programming Guide》(鍵值編碼編程指南)。

創(chuàng)建字典

您可以使用分配、初始化,或者類工廠方法來創(chuàng)建字典,如下所示:

NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
               someObject, @"anObject",
         @"Hello, World!", @"helloString",
                      @42, @"magicNumber",
                someValue, @"aValue",
                      nil];

對于 dictionaryWithObjectsAndKeys: 和 initWithObjectsAndKeys: 方法,每個(gè)對象都會在其鍵前進(jìn)行聲明,并且對象列表和鍵必須以 nil 結(jié)束。

Objective-C 提供了一種簡潔的語法來創(chuàng)建字典字面常量。

NSDictionary *dictionary = @{
              @"anObject" : someObject,
           @"helloString" : @"Hello, World!",
           @"magicNumber" : @42,
                @"aValue" : someValue
};

對于字典字面常量,鍵會在其對象前被指定,并且對象列表和鍵不以 nil 結(jié)束。

查詢字典

創(chuàng)建字典后,您可以查詢儲存在給定鍵中的對象。

NSNumber *storedNumber = [dictionary objectForKey:@"magicNumber"];

如果找不到該對象,objectForKey: 方法會返回 nil。

同樣也可以用下標(biāo)語法來替代 objectForKey:。

NSNumber *storedNumber = dictionary[@"magicNumber"];

可變性

創(chuàng)建字典后,如果需要添加或移除對象,可使用 NSMutableDictionary 子類。

[dictionary setObject:@"another string" forKey:@"secondString"];
[dictionary removeObjectForKey:@"anObject"];

使用 NSNull 表示 nil

因?yàn)樵?Objective-C 中,nil 表示“無對象”。因此不可能將 nil 添加到此節(jié)所描述的集類中。如果要在集 (collection) 中表示“無對象”,應(yīng)使用 NSNull 類。

NSArray *array = @[ @"string", @42, [NSNull null] ];

使用 NSNull,null 方法始終都會返回相同的實(shí)例。按此方式工作的類稱為單例類。您可以按如下所示的方法來檢查數(shù)組中的對象是否等于已共享的 NSNull 實(shí)例:

for (id object in array) {
    if (object == [NSNull null]) {
        NSLog(@"Found a null object");
    }
}

雖然 Foundation 框架包含的功能比文中所述要豐富的多,但也不需要您立即了解每一處細(xì)節(jié)。如果確實(shí)想更深入學(xué)習(xí) Foundation,可以參閱《Foundation Framework Reference》(Foundation 框架參考)?,F(xiàn)在,您已經(jīng)掌握了足夠的信息來繼續(xù)完成 ToDoList 應(yīng)用程序了,那么就從編寫自定數(shù)據(jù)類開始吧。