Foundation Framework(2)
集合類
用來存儲和管理一組對象的類
- 三種常用的集合類
NSArray:強調順序,但是里面的元素可以相同
NSDictionary:鍵值對的形式,鍵不講究順序
NSSet:不強調順序,元素是互不相同的
創建NSArray對象
方法一:
NSArray *array = [NSArray arrayWithObjects:@"str1", @"str2", @"str3", nil];
//調用了NSArray的工廠方法
//用nill標記序列的結束
方法二:
NSArray *array = [[NSArray alloc] initWithObjects:@"str1", @"str2", @"str3", nil];
方法三:
就像NSString創建字符串對象很常見一樣,創建數組也太常用了,所以,OC為創建數組提供了一種簡單的語法:
NSArray *array = @[@"str1", @"str2", @"str3"];
數組里的nil是結束標志,如果在中間出現nil,就會被認為這是末尾。但如果我們確實想在中間元素中有個空值,那這么辦?
NSNull *null = [NSNull null];
//使用NSNull類(單例類)創建一個 null對象
//注意null 與nil的區別,null是有對象的,只是這個對象是空的,它只是用來占位的。而nil是真的沒有一個對象。
注意:NSArray只能存儲對象!
基本數據類型,比如C語言里的int,float,double, 結構體等,以及Foundation Framework里的NSInteger 都不能存儲在NSArray里,因為它們都不是對象。
但如果確實想存儲這些類型,怎么辦?
Foundation Framework 提供了基本數據類型的包裝對象。也就是說我們可以把這些基本數據類型包裝在一個對象里面,這樣就可以把這些數據作為對象來處理了。
包裝類
- NSNumber
NSNumber 提供的把基本數據類型轉換為對象的方法
NSNumber *intNum = [NSNumber numberWithInt:20];
NSNumber *doubleNum = [NSNumber numberWithDouble:20.5];
NSNumber *floatNum = [NSNumber numberWithFloat:98.98787f];
NSNumber *boolNum = [NSNumber numberWithBool:YES];
//使用NSNumber類方法,把基本數據類型當作參數傳進去,這個方法就會返回一個NSNumber對象
如何把NSNumber對象里的數值取出來用?
int a = [intNum intValue];
double b = [doubleNum doubleValue];
float c = [floatNum floatValue];
BOOL d = [boolNum boolValue];
//每個對象都有特定的方法,可以返回特定類型的數據
每次要創建NSNumber對象的時候,都要調用NSNumber的類方法,很麻煩,有沒有方便的辦法?
ObjC2.0后,提供了更方便的字面量的寫法。
NSNumber *intNum = @20;
NSNumber *doubleNum = @20.5;
NSNumber *floatNum = @98.98787f;
NSNumber *boolNum = @YES;
NSNumber可以對C語言的基本數據類型進行封裝(成為對象),但是對于更復雜的,比如結構體,字節序列等,就得用另外一種方式進行封裝,用NSNumber的父類,NSValue來處理。
- NSValue
如何把一個結構體包裝進NSValue并生產一個NSValue對象?
typedef struct {
int a;
float b;
}DataType;
//這是個結構體,是無法包裝進一個NSNumber里的
使用NSValue來包裝結構體
DataType data;//定義一個結構體變量
NSValue *value = [NSValue valueWithBytes:&data objCType:@encode(Data Type)];
//調用NSValue的類方法,傳入data的指針,
//第二個參數是data的數據類型(這個例子data的數據類型是結構體)
//如此這般便創建出一個NSValue對象
//注意`encode`是OC的關鍵字,可以得到數據類型的C的字符串表示。
//也就是說,`@encode(DataType)`返回的是`DataType`這么一個字符串
如何把包裝在NSValue對象(Value)里的數據取出來?
[value getValue:&data];
//傳入data變量的地址,getValue方法就會把包裝起來的數據重新寫回到我們傳入的這個地址里,
//然后就可以直接使用里面的數據了。
現在我們有了NSNumber 和NSValue,我們就可以把各種數據類型寫進NSArray數組里了。
讀取NSArray某個下標位置的對象
- (id)objectAtIndex:(NSUInteger)index;
一個例子
NSArray *arrayOfString = @[@"str1", @"str2", @"str3", @"str4"];
NSString *str = [arrayOfString objectAtIndex:2];//返回第三個字符串的指針
//這個方法還是麻煩
更簡潔的寫法
NSString *str = arrayOfString[2];//跟C語言數組用法一樣
另一個常用的集合類,NSDictionary
在字典里我們可以很方便的根據一個鍵來找到對應的數值。
對于字典的鍵,需要注意兩點:
字典的鍵,必須是不可變對象
字典的鍵,必須兩兩不相同
- 如何創建一個字典
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
@64, @"intValue";
@19.8, @"doubleValue";
@YES, @"boolValue", nil];
//調用NSDictionary的一個工廠方法dictionaryWithObjectsAndKeys:
//注意先寫值對象,再寫鍵對象
//最后的nil也是用來判斷傳入參數序列的結束
- 字面量的創建方式
NSDictionary *dict = @{@"intValue":@64,
@"double":@19.8,
@"boolValue":@YES};
//鍵寫在前面,后面是值
- 如何根據字典的鍵查找對應的值?
第一種方式
- (id)objectForKey:(id)aKey;
e.g.
NSObject *obj = [dict objectForKey:@"intValue"];
精簡版
NSObject *obj = dict[@"intValue"];
//看著有點像數組的用法,只是數組下標變成了字典鍵
集合類NSSet
NSSet使用頻率較低,當使用它是一般是考慮到效率問題。
當我們要判斷一個集合里是不是有一個對象的時候,一個方法是使用NSArray數組掃一遍。而使用NSSet不需要遍歷,效率高了很多。
- 如何創建一個NSSet對象?
NSSet *set = [NSSet setWithObjects:@"A", @"B", @"C", @"D", nil];
//跟NSArray類似,這也是運用類里的工廠方法來生成對象
- 如何判斷一個集合里是否包含某個對象?
BOOL isContained = [set containsObject:@"A"];
//如果包含,則返回YES,否則返回NO.
因為NSSet使用頻率不高,所以OC沒提高更簡便的方法