Foundation框架
NSObject
iOS SDK中基本上是每个对象的基类
实现前面所讨论的内省方法
- (NSString *)description是一个实用的重写方法 (它是NSLog( )中的%@).
例如...
NSLog(@“array contents are %@”, myArray);
%@替换了调用[myArray description]的结果
复制对象。这是一个需要明白的重要概念(为什么可变VS不可变?)
- (id)copy; //不是所有对象的实现途径(如果不是则引发异常)
- (id)mutableCopy; //不是所有对象的实现途径(如果不是则引发异常)
这不少见,有一个数组或字典,做出一个mutableCopy可以修改
或者有一个可变数组或字典,copy他来“冻结”,是它不可变
制作集合类的副本非常有效,因此这么做不用出汗
NSArray
对象的有序集合
不可变。这是对的,一旦你创建数组,你不能添加或删除对象。
数组中所有对象都被strong的保持住
通常通过操作其他数组或者@[ ]创建
你已经知道这些关键方法...
- (NSUInteger)count;
- (id)objectAtIndex:(NSUInteger)index; //如果下标越界会崩溃:返回id!
- (id)lastObject; //如果数组中没有对象返回nil(不会崩溃)
- (id)firstObject; //如果数组中没有对象返回nil(不会崩溃)
不过这个类里有大量非常实用的方法。比如...
- (NSArray *)sortedArrayUsingSelector:(SEL)aSelector;
- (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)selectorArgument;
- (NSString *)componentsJoinedByString:(NSString *)separator;
NSMutableArray
NSArray的可变版本
创建用alloc/init或者...
+ (id)arrayWithCapacity:(NSUInteger)numItems; //项目数只是一个性能提示
+ (id)array; // [NSMutableArray array]就像 [[NSMutableArray alloc] init]
NSMutableArray继承NSArray
所有的方法
不只是count、objectAtIndex:等
而且你知道,它实现了这些关键的好方法...
- (void)addObject:(id)object; //到数组的结尾 (注意是id类型!)
- (void)insertObject:(id)object atIndex:(NSUInteger)index;
- (void)removeObjectAtIndex:(NSUInteger)index;
枚举器
在高效地方式中从头到尾循环数组中的成员
语言支持使用for-in
例如:NSString对象的NSArray
NSArray *myArray = ...;
for (NSString *string in myArray) { //编译器没有办法知道myArray包含什么
double value = [string doubleValue]; //如果string不是一个NSString,这里会崩溃
}
例如:id的NSArray
NSArray *myArray = …;
for (id obj in myArray) {
//利用boj做些什么,但要确保你不向它发送一个消息,它不回应
if ([obj isKindOfClass:[NSString class]]) {
 //发送NSString消息给obj是不用担心的
}
}
NSNumber
对象
包装,围绕基本类型如果int、float、double、BOOL、enums等
NSNumber *n = [NSNumber numberWithInt:36];
float f = [n floatValue]; //将返回一个float型的36.0(即,将转换类型)
当你想要把这些基本类型放入集合(例如NSArray或NSDictionary)中,很不错
在iOS 6中创建NSNumber的新语法:@( )
NSNumber *three = @3;
NSNumber *underline = @(NSUnderlineStyleSingle); //枚举
NSNumber *match = @([card match:@[otherCard]]); //表达式返回一个基本类型
NSValue
为一些非对象,非原始数据类型通用的对象包装(即,C结构体)
例如
NSValue *edgeInsetsObject = [NSValue valueWithUIEdgeInsets:UIEdgeInsetsMake(1,1,1,1)]
在课程中也许并不需要这个(我们开始使用points, sizes and rects时)
NSData
“bits的包”。用来保存/恢复/发送原始数据,遍及iOS SDK
NSDate
用来查找当前时间或者去存储过去或将来的时间/日期
另请参见NSCalendar, NSDateFormatter, NSDateComponents
如果你将在你的UI中显示日期,请确保详细地学习了这个(本地化)
NSSet / NSMutableSet
像一个数组,但没有顺序(没有objectAtIndex:方法)
member:是一个重要的方法(在set里isEqual:对象,如果有一个,返回它)
可以结合和交叉其他的set
NSOrderedSet / NSMutableOrderedSet
介于NSArray与NSSet之间的种类
在一组有序的set中对象们是不同的,你不能像数组一样多次放入相同的对象
NSDictionary
通过key查询对象的不可变集合(简单的哈希表)
所有的key和values通过NSDictionary被strong的保持着
可以用这样的语法创建:@{ key1 : value1, key2 : value2, key3 : value3 }
NSDictionary *colors = @{ @“green” : [UIColor greenColor],
@“blue” : [UIColor blueColor],
@“red” : [UIColor redColor] };
查询使用起来“像数组”符号...
NSString *colorString = ...;
UIColor *colorObject = colors[colorString]; //工作方式等同于objectForKey:
- (NSUInteger)count;
- (id)objectForKey:(id)key; // key必须是copyable并且正确地实现isEqual:
NSString适合做key正因如此
更多关于如何才能成为一个key参见NSCopying协议
NSMutableDictionary
NSDictionary的可变版本
创建使用alloc/init或者+ (id)dictionary...其中之一的类方法
除了所有从NSDictionary中继承的方法,这里有一些重要的方法...
- (void)setObject:(id)anObject forKey:(id)key;
- (void)removeObjectForKey:(id)key;
- (void)removeAllObjects;
- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary;
枚举器
从头到尾地循环字典中的key或values
例如:
NSDictionary *myDictionary = ...;
for (id key in myDictionary) {
//这里做一些key参与的事
id value = [myDictionary objectForKey:key];
//这里做一些value参与的事
}
属性列表
术语“属性列表”的意思只是集合的集合
这只是一种习语(不是语言的事)。它意思是对象
的一些图表,包含的仅是:
NSArray, NSDictionary, NSNumber, NSString, NSDate, NSData(或者他们的可变的子类)
NSArray是一个属性列表,
如果它所有的成员也是
所以一个NSString的NSArray是一个属性列表
所以是一个NSArray的NSArray,只要那些NSArray的成员是属性列表
NSDictionary是一个属性列表,
如果所有的key和values也是
key是NSString,values是NSNumber的字典的数组是属性列表
为什么定义这个术语?
因为SDK有很多的属性列表的操作方法
通常从某处读取它们或把它们写在某处。例如:
- (void)writeToFile:(NSString *)path atomically:(BOOL)atom;
这个能(只能)被发送到一个NSArray或NSDictionary中,包含的仅是属性列表对象
其他的Foundation
NSUserDefaults
属性列表的轻量级存储
它基本上是你的应用程序的启动与结束之间仍然存在的一个NSDictionary
不是一个完整的数据库,所以只存储像用户偏好这样的小东西
读和写是通过一个共享的实例(单例),通过类方法standardUserDefaults取得...
[[NSUserDefaults standardUserDefaults] setArray:rvArray forKey:@“RecentlyViewed”];
样本方法:
- (void)setDouble:(double)aDouble forKey:(NSString *)key;
- (NSInteger)integerForKey:(NSString *)key; //NSInteger是一个32或64位int的typedef
- (void)setObject:(id)obj forKey:(NSString *)key; //obj必须是一个属性列表对象
- (NSArray *)arrayForKey:(NSString *)key; //如果键的值不是NSArray将返回nil
始终记得每次变更的批处理之后写入defaults!
[[NSUserDefaults standardUserDefaults] synchronize];
NSRange
C结构体(不是类)
用来指定字符串和数组(等等)内部的子范围。
typedef struct {
NSUInteger location;
NSUInteger length;
} NSRange;
重要的location值NSNotFound
NSString *greeting = @“hello world”; NSString *hi = @“hi”;
NSRange r = [greeting rangeOfString:hi]; //找出hi字符在greeting内的范围
if (r.location == NSNotFound) { /*在greeting中未发现NSNotFound*/ }
NSRangePointer(只一个NSRange *用于外部方法的参数)
这里是C函数,就像NSEqualRanges( ), NSMakeRange( )等