Foundation框架
1、Foundation框架概况
前面我们已经提过Foundation框架含有100多个类、14000多行代码、占近1M的存储空间。它是Application kit和UIKit框架的基础。它包含了很多有用的面向数据的简单类和数据类型,如结构体、NSString、NSArray、NSEnumerator和NSNumber等。在oc程序中都有Foundation框架的引入。
2、结构体(struct)
Foundation框架保留了Core Foundation框架中的部分结构体类型,他们是用c语言编写的。如表示范围的NSRange、用于几何图形处理的CGPoint、CGSize、CGRect等。在框架中用于处理几何图形的数据类型都带有CG前缀。同时,Cocoa还为创建这些数据类型提供了快捷函数:NSMakeRange()、CGPointMake()、CGSizeMake()和CGRectMake()。
Cocoa中延续了采用c语言编写的结构体而不是对象,这是因为所有的oc对象都是动态分配的,在对象创建时将消耗大量的时间,而采用c编写的结构体数据类型在使用的过程中能大大的提高代码的性能。
3、NSString类
NSString类是Cocoa种用来处理字符串的类。在使用NSString类型数据时我们常常使用一种被称为字面量的语法结构,NSString字面量的标志为双引号内字符串前面的@符号。这里提及一下在c语言中是采用字符数组对字符串进行处理的。
NSString类提供了一些处理字符串的方法:
1) +(id)stringWithFormat:(NSString *) format,…;
这是一个通过格式字符串和参数来创建字符串的NSString类的类方法。(…)中内容为与格式字符串中相对应的参数,参数之间用逗号隔开。这里在提及一下‘+’表示所声明的是类方法,‘-’表示所声明的是实例方法。
e.g: NSString *height=[NSString stringWithFormat:@”your height is %d,feet %d inches”,60,42];//表示创建了一个NSString*类型的对象,该对象指向“your height is 60,feet 42 inches”字符串。
2) -(NSUInger)length;
这是NSString类提供的用于返回字符串中字符个数的方法。
e.g: NSUInteger length=[height length];//该方法能够精确无误的处理各种国际语言的字符串;而c语言中音位国际语言占用的字节不一致如果调用strlen()函数计算字节数将返回错误的结果。
3) -(BOOL)isEqualToString:(NSString *)aString;
这是NSString类提供的用于比较两个字符串是否相等的方法。该方法返回一个BOOL值(YES或NO)。
这里要说一点,‘==’运算符判断的是两个对象的指针数值是否相等,而使用方法能判断两个对象的内容是否相等。请注意它们在不同场合的使用。
4) -(NSComparisonResult)compare:(NSString *)aString;
这个方法将接收对象和传递过来的字符串逐个进行比较,区分大小写,它返回一个NSComparisonResult枚举类型的值来表示比较的结果。
该枚举类型为:
enum
{
NSOrderedAscending=-1,
NSOrderedSame,
NSOrderedDescending
}
Typedef NSInteger NSComparisonResult;
当调用上面的方法返回的值是NSOrderedAscending时,表示接受对象小于传递对象,即比较的目标在字母表中的排列位置比传递进来的字符串更靠前。其它返回值类推即可。
该例子中通过rangeOfString:方法将检查NSString类对象fileName中字符串是否含有chapter字符串。如果有将返回chapter字符串的起始位置以及字符个数并保存在NSRange结构体变量range中。如果无法找到将返回NSNotFound值给range中location成员变量。
4、NSMutableString类
NSString类的对象中字符串是不可变的,即NSString类对象一旦被创建便不能更改。也就是说该类对象中的字符串不能以删除字符或者添加字符的方式来改变它。Cocoa为我们提供了一个NSString的子类NSMutableString,它可以对所创建对象中的字符串进行更改。
在NSMutableString中的相关方法:
1) + (id) stringWithCapacity: (NSUInteger) capacity;
该方法可以创建一个可变字符串NSMutableString类的对象。而且,它还将为该字符串对象的大小提供一个最优值。所谓最优值也就是指该方法为字符串对象预分配了一块内存空间,所存储的字符串并不受最优值的限制。
2) - (void) appendString: (NSString*) aString;
该方法将接收到的参数值复制到接收对象的末尾。
3) - (void) appendFormat: (NSString*) format,…;
该方法将格式化的字符串附加到接收对象的字符串末尾。
4) - (void) deleteCharactersInRange: (NSRange) aRange;
该方法能将接收对象的字符串中指定位置指定长度的字符串删除。
Cocoa提供了许多集合类,如NSArray和NSDictionary。集合类只能存储objective-C的对象,不能存储原始的c语言基础数据类型,如int、float、enum、struct等。同样,集合类中不得存入nil(对象的零值或NULL值)。这里我们先说说NSArray集合类。
5、NSArray类
NSArray是用来存储对象的有序列表,你可以将任意类型的对象放入NSArray中。当然它也具备集合类的特点,不能存入c语言中基础数据类型,不能存入nil。
NSArray类中的相关方法:
1) + (NSArray *) arrayWithObjects:(id) object1,…,nil;
该类方法将创建一个NSArray类的对象。方法参数部分是以逗号分隔的对象列表,在列表结尾添加nil表示结束。
在oc中还提供了一种叫字面量的创建方法,它的表示是以方括号前面的@表示。
注意在字面量表示中不要用nil。
2) -(NSUInteger) count;
该方法可以获取数组对象中所包含的对象个数。
3) -(id) objectAtIndex: (NSUInteger) index;
该方法可以获取数组中特定索引处的对象。
在oc中也提供了通过字面量访问数组的语法,它与c语言中访问数组项的语法类似。
4) -(NSArray *)componentsSeparatedByString:(NSString *)separator;
该方法可以将NSString类型字符串按参数中指定的字符串分割成一个NSArray类型的数组。
5) -(NSString*) componentsJoinedByString:(NSString*)component;
该方法可以将NSArray类型数组中的对象按参数中指定的字符串组合成一个NSString类型的字符串。
NSArray数组的基本特性:
NSArray类的对象中只能存储对象,不能存储c中基本数据类型。
NSArray类的对象中不能存储nil(对象的零值或NULL)。
NSArray类的对象一但建立就不能通过添加或删除对象元素改变对象的大小。
NSArray类的对象在访问时不得越界,否则oc运行时将会报错。错误类型:NSRangeException(范围异常)。
6、NSMutableArray可变数组
上面已经说了Cocoa中不可变数组NSArray,接下来我们将介绍Cocoa中提供的可变数组类型NSMutableArray。使用可变数组类可以随意地添加或删除数组中的对象。
NSMutableArray可变数组中的相关方法:
1) +(id) arrayWithCapacity:(NSUInteger) numItems;
该方法可创建可变数组类的对象,它将为对象预分配一个最优值存储空间,也就是说该容量值并不会限制数组的大小。
2) -(void) addObject:(id) anObject;
该方法用于在数组末尾添加新的对象成员。
3) -(void) removeObjectAtIndex:(NSUInteger) index;
该方法可以删除指定索引处的对象。注意,索引从零开始。当删除一个对象后,数组中并不会留下漏洞,位于被删除对象后面的数组元素都将前移来填补空缺。
可变数组类型的特点:
我们可以对可变数组进行添加或删除操作。
可变数组中没有相关的字面量操作。
可变数组只能用于存放对象。
可变数组中不能存放nil对象。
7、枚举
在程序中我们可以使用从0到[array count]的循环来读取每个索引处的对象,同样,Cocoa也为我们提供了一种枚举型NSEnumerator来表示集合中迭代出的对象。
要想使用NSEnumerator,你必须先通过objectEnumerator向数组请求枚举器。方法体如下:
-(NSEnumerator*)objectEnumerator;
该方法使用如下:
NSEnumerator * enumerator = [array objectEnumerator];
例子中集合体对象发送objectEnumerator消息,并将迭代出来的对象放入枚举器中。
上面的方法是将集合体对象中的对象按从前往后的顺序放入枚举器中,Cocoa中还提供了一种从后往前浏览集合的方法reverseObjectEnumerator。方法声明为:
-(NSEnumerator*)reverseObjectEnumerator;
在获得集合体对象的枚举器后,我们便可以通过while循环方式来检测枚举器中的每一个对象并进行调用。依序获取枚举器中对象的方法为:
-(id) nextObject;
在while循环中,该方法每调用一次获取枚举器中的一个对象,当返回nil值时,循环结束。
注意,在进行枚举操作时,不得对可变数组进行添加或删除对象之类改变数组大小的操作。否则,oc运行时将会出错,你可能获得一个未定义结果。
8、快速枚举
上面我们介绍了枚举器的使用,这里我们将说一说快速枚举的使用。
在快速枚举中,通过in指向一个集合体来对集合体中的成员对象进行遍历。注意,快速枚举不能使用在Mac OS X 10.5之前的系统中。
9、代码块枚举方法
方法声明如下:
-(void)enumerateObjectsUsingBlock: (void (^)(id obj,NSUInteger idx,BOOL *stop))block;
这里先不讲代码块的相关知识,只是提及一下它在集合体中迭代访问成员对象的方法。它在NSArray数组中的使用如:
[array enumerateObjectsUsingBlock:^(NSString *string,NSUInteger index,BOOL *stop){ NSLog(@”I found%@”,string);}];
通过代码块枚举可以让循环操作并发执行。
上面我们分别介绍了4中方法来遍历数组:通过索引、NSEnumerator枚举、快速枚举和代码块枚举。代码块枚举只能在Apple LLVM编译器上才会有效。索引访问数组方法-objectAtIndex一般用在跳跃式访问数组或同时遍历多个数组时。
10、NSDictionary类
前面我们介绍了集合类NSArray,这里我们将介绍另一个集合类NSDictionary。NSDictionary能在给定的关键字(通常指NSString字符串)下存储一个数值(任意类型的Objective-c对象),你可以通过这个关键自来查找相应的数据。这种利用关键字查找对象的方式通常也称作字典。
比起NSArray数组中的按序查找,NSDictionary字典查找有着很大的优势。字典查找是一种键值查询方式,它可以立即找出要查询的数据,而不用遍历整个数组。对于频繁的查询和大型的数据集使用字典比数组快得多。
NSDictionary类的相关方法:
1) +(id) dictionaryWithObjectsAndKeys:(id)firstObject,…;
该方法中参数先存储对象,然后紧跟关键字,接收的参数对象和关键字交替出现,以nil值作为终止符号。
同样,Cocoa也提供了创建字典的字面量方法。其形式为@{key:value,…}。在字面量语法中关键字在前,数值对象在后,关键字和数值对象之间以冒号分开,而每对键值之间则用逗号隔开。
2) -(id) objectForKey: (id) akey;
该方法可以获取字典对象中指定键的数据对象,通过它可以访问字典中任意数值对象。也可使用字面量访问,如:dictionary[key3];表示访问字典中键为key3的数据对象。注意,当无法找到字典中与键对应的数值时,字典将返回nil值。
11、NSMutableDictionary类
同NS String和NSArray类一样,NSDictionary也是不可变的,不能对NSDictionary对象进行添加或删除等操作。但Cocoa同样也提供了可变字典类NSMutableDictionary。
创建一个可变字典类的对象的方法:
+ (id) dictionaryWithCapacity: (NSUInteger) numItems;
该方法为新建的字典对象分配一个最优值大小的存储空间,这个值并不会限制可变字典的大小。
向可变字典中添加元素的方法:
- (void) setObject: (id)an0bject forKey: (id) aKey;
该方法第一个参数为字典添加一个对象,第二个元素为所添加的对象指定一个键。注意,如果字典中已存在所添加的键,则将会用新的对象替换掉原有对象。
删除可变字典中的一些关键字的方法:
- (void) removebjectForKey: (id) aKey;
该方法将删除字典中指定关键字及其相关的对象。
这里提及一点,在可变的类型中都没有用于初始化的字面量语法。
12、NSNumber类
前面已经说过集合类都只能存放对象,不能存放c语言中的基本数据类型。然而,Cocoa提供了NSNumber类来封装基本数据类型。
可以使用以下方法来创建不通基本数据类型的对象:
+ (NSNumber*) numberWithChar:(char) value;
+ (NSNumber*) numberWithInt:(int) value;
+ (NSNumber*) numberWithFloat:(float) value;
+ (NSNumber*) numberWithBool:(BOOL) value;
上面列举来最常用的四种基本数据类型方法的声明,当然还有很多中基本的数据类型,它们的声明都类似。
同样,除了使用创建方法外,Cocoa还提供了相应的字面量来创建不通基本数据类型的NSNumber对象。
不通基本类型字面量创建NSNumber对象举例:
NSNumber * number;
Number = @’X’; //字符型
Number = @12345;//整型
Number = @12345ul;//无符号长整型
Number = @12345ll;//long long型
Number = @123.45f;//浮点型
Number = @123.45;//双浮点型
Number = @YES;//布尔型
通过上面的方式转换后就可以把它们以NSNumber类的对象放入数组或字典中了。
上面讲了如何把基本数据类型封装到NSNumber类的对象中,现在我们讲一下如何将封装在NSNumber类的对象中的数据取出来。
在面举一些常用类型数据获取的相关实例方法:
(char) charValue;
(int) intValue;
(float) floatValue;
(BOOL) boolValue;
(NSString *) stringValue;
这里提及一点,将创建方法和提取方法搭配使用时,NSNumber可以对数据进行适当的转换。
13、NSValue类
上面讲的NSNumber是NSValue的子类,NSValue可以封装任意值。
创建一个NSValue 对象的类方法:
+ (NSValue *) valueWithBytes: (const void *) value objCType: (const char *) type;
该方法中第一个参数是要封装成NSValue类型的数据存储的地址;第二个参数是用来描述第一个参数的数据类型,一般用@encode编译器指令来将接收的数据类型的名称转化成合适的字符串。
举例,将结构体转化成NSValue类型的对象并放入NSArray数组中:
NSRect rect = NSMakeRect(1,2,30,40);
NSValue *value = [NSValue valueWithBytes: &rect objCType: @encode(NSR ect)];
NSMutableArray *array = [NSMutableArray arrayWithCapacity:20];
[array addObject:value];
在例中可以看到该方法将之前转化成NSValue类型的原数据类型的对象的存储地址作为了参数。
Cocoa中还提供了将一些常用的struct类型的数据转换成NSValue类型的便捷方法:
+ (NSValue *) valueWithPoint: (NSPoint) aPoint;
+ (NSValue *) valueWithSize: (NSSize) size;
+ (NSValue *) valueWithRect: (NSRect) rect;
- (NSPoint) pointValue;
- (NSSize) sizeValue;
- (NSRect) rectValue;
上面的快捷方法都同例子中使用。
14、NSNull类
我们曾说过在集合类的对象中是不可以使用nil(对象的零值或NULL值)的,然而当我们需要存入的对象本身就是空的怎么办呢?这里Cocoa为我们提供了NSNull类,它将可以在集合对象中存入一个空对象。
方法如下:
+(NSNull*)null;
在Cocoa中NSNull中只有这个唯一的方法,举个该方法在字典中的运用:
[contact setObject: [NSNull null] forKey:@”home fax machine”];
访问如下:
id homefax = [contact objectForKey:@”home fax machine”];
if(homefax ==[NSNull null])
{
//确定为空对象的行为
}
注意,[NSNull null]总是返回一样的数值,所以可以使用==运算符来与其它的值进行比较。
15、类簇
在Cocoa中,许多类是以类簇的方式实现的,即它们是一批隐藏在通用接口类之下的与实现相关的类。举个例子,如创建NSString对象时,实际上调用的可能是NSLiteratalString、NNSCFString、NSSimpleCString、NSBallOfString或是NSString接口下其它的类。因此,不要轻易创建NSString、NSArray或NSDictionary的子类,最好是不要这样做。