1.前言
Cocoa由两个不同的框架组成:
Foundation Kit 框架:面向对象的低级类(如NSObject)和数据类型。
Application Kit 框架:所有用户接口对象和高级类。
Foundation 框架知识Cocoa的一部分,没有内置于Objective-C语言中。
2.一些有用的数据类型
Cocoa为我们提供了一些结构体(struct)。
2.1范围结构体NSRange
typedef struct _NSRange
{
unsigned int location;
unsigned int length;
}NSRange;
范围结构体NSRange用来表示相关事物的范围,location表示该范围的起始位置,length表示该范围所包含元素的个数。
location还可以用NSNotFound这个值表示没有范围,比如变量没有初始化。
创建NSRange的方式有三种:
第一种,直接赋值:
NSRange range;
range.location = 17;
range.length = 4;
第二种,应用C语言的聚合结构赋值机制:
NSRange range = {17,4};
第三种,Cocoa提供的快捷函数NSMakeRange():
NSRange range = NSMakeRange(17, 4);
2.2 几何数据类型
Core Graphics框架提供了用来处理几何图形的数据类型,例如CGPoint和CGSize。Core Graphics是有C语言所写,所以可以再代码中使用C语言的数据类型。
CGpoint 表示笛卡尔平面的一个坐标(x, y)。
struct CGPoint
{
float x;
float y;
};
CGSize用来存储长度和宽度:
struct CGSize
{
float width;
float height;
};
Cocoa提供了一个矩形数据类型,它由坐标和大小复合而成:
struct CGRect
{
CGPoint origin;
CGSize size;
};
以上这些数据类型的快捷函数是:CGpointMake( )、CGSizeMake()和CGRectMake()。
这些数据类型采用结构体而不是对象,原因是为了提高性能。所有的Objective-C对象都是动态分配内存的,而动态分配内存是一个代价较大的操作。
3.字符串类型NSString
3.1创建字符串
NSString 的stringWithFormat:方法通过格式字符串和参数来创建NSString
+(id)stringWithFormat:(NSString *)format, … ;
NSString height = [NSString stringWithFormat:@“Your height is %d feet, %d inches”,5,11];
3.2类方法
Objective-C运行时生成一个类的时候,会创建一个代表该类的类对象(class object)。类对象,包含了指向超类、类名和类方法列表的指针,还包含一个long类型的数据,为新创建的实例对象指定大小(以字节为单位)。
类方法(或称 工厂方法)的开头有一个+加号,创建的是类对象,而不是类的实例对象。
+(id)stringWithFormat:(NSString *)format, … ;
就是一个类方法
如果某个方法所实现的是很通用的功能,比如创建一个实例对象或者访问一些全局类数据,那么最好使用加号(+)作为前缀,将它声明为类方法。
如果方法只是在指定的对象实例中起作用,比如获取一个Circle的颜色或者一个Tire的压强,则用减号(-)作为前缀进行声明。
3.3字符串大小
-(NSUInteger)length;
这个实例方法返回的是字符串中的字符个数。
使用:
NSUInteger length = [height length];
3.4字符串的比较
-(BOOL)isEqualToString:(NSString *)aString;
返回一个BOOL值(YES或者NO)来表示两个字符串的内容是否相同。
注意:如果想检查两个字符串是否内容相等,应该使用isEqualToString
如果是检查两个对象是否为同一事物(即指针数值是否相同),应该用运算符==。
-(NSComparisonResult)compare:(NSString *)aString;
compare:将接受对象和传递过来的字符串逐个进行比较,它返回一个NSComparisonResult(一个enum型枚举)来显示比较结果。
enum
{
NSOrderedAscending == -1,
NSOrderedSame,
NSOrderedDescending
};
typedef NSInteger NSComparisonResult;
3.5不区分大小写的比较
compare进行的是区分大小写的比较。
以下方法提供更多比较的类型:
-(NSComparisonResult)compare:(NSString :)aString options:(NSStringCompareOptions )mask;
options参数是一个掩位码。常用的选项如下:
NSCaseInsensitiveSearch:不区分大小写字符。
NSLiteralSearch:进行完全比较,区分大小写字符。
NSNumericSearch:比较字符串的字符个数,而不是字符串值。
例如比较两个字符串,忽略大小写并且按照字符个数进行排序,这样这么做:
if ([thing1 compare: thing2 options: NSCaseInsensitiveSearch | NSNumbericSearch] == NSOrderedSame)
{
NSLog(@"They match!");
}
3.6字符串内是否包含其他字符串
- (BOOL) hasPrefix: (NSString *) aString;//检查字符串是否以另一个字符串开头
- (BOOL) hasSuffix: (NSString *) aString;//检查字符串是否以另一个字符串结尾
- (NSRange) rangeOfString: (NSString *) aString;//检查字符串的某处是否包含另一个字符串。
4 NSMutableString
NSString是不可变的,但其子类NSMutableString是可变的:
+(id)stirngWithCapacity:(NSUInteger)capacity;
创建一个新的NSMutableString,
这个容量capacity是给NSMutableString一个初始大小,可以超过其大小。例如,如果你要创建一个大小为40M的字符串,那么NSMutableString可以预分配一块内存来存储它,这样后续的操作速度会快很多。
- (void)appendString:(NSString *)aString;
- (void)appendFormat:(NSString *)format, …;
没有创建新的字符串,而是将格式化字符串附加在了接收字符串的末尾。
-(void)deleteCharactersInRange:(NSRange)aRange;
删除字符串中的字符。
这个方法常常和rangeOfString一起使用。
5 集合家族
5.1 NSArray
NSArray是一个Cocoa类,用于存储对象的有序列表,可以存放任何类型的对象.
但NSArray有两个限制:
- 只能存储Objective-C对象,不能存储C语言中的基本数据类型,如int,float,enum,struct..etc
- 不能存储nil(对象的零值或NULL值)
5.1.1创建
NSArray *array = [NSArray arrayWithObjects: @"One", @"Two", @"Three", nil];
结尾的nil表示列表结束。
或者使用字面量语法:
NSArray *array = @[@“one”, @“two”, @“three”];
使用字面量语法,不需要在结尾补上nil。
5.1.2对象个数
-(NSUInteger)count;
5.1.3获取索引元素
-(id)objectAtIndex:(NSUInteger)index;
5.1.4切分与合并
使用-componentsSeparatedByString:可以切分NSArray,像这样:
NSString *string = @“oop:ack:bork:greeble:ponies”;
NSArray *chunks = [string componentsSeparatedByString:@“:”];
使用-componentsJoinedByString:合并NSArray中的元素并创建字符串:
string = [chunks componentsJoinedByString:@“:-)”];
5.2 NSMutableArray
NSMutableArray可以删除和添加元素。
5.2.1 创建
+(id)arrayWithCapacity:(NSUInteger)numItems;
5.2.2 添加与删除
-(void)addObject:(id)anObject;
-(void)removeObjectAtIndex:(NSUIngeter)index;
5.2.3枚举
NSArray经常要对数组中的每一个元素都执行同一个操作,你可以编写一个从0到[array count]的循环来读取每个索引处的对象,也可以用NSEnumerator。Cocoa用它来表示集合中迭代出的对象。
向数组请求一个枚举器
NSEnumerator *enumerator = [array objectEumerator];
如果想从后往前浏览某个集合,使用reverseObjectEnumerator方法。
在获得枚举器后,开始一个while循环,每次循环都向这个枚举器请求下一个对象:
-(id)nextObject;
nextObject返回nil时,循环结束。
整个循环代码如下:
NSEnumerator *enumerator = [array objectEumerator];
while(id thingie = [enumerator nextObject])
{
NSLog(@“I found %@”,thigie);
}
5.2.4 快速枚举
苹果公司在Objective-C2.0总引入了快速枚举(fast enumeration)。快速枚举不恩能够在旧的Mac(Mac OS X 10.5之前的)系统上运行。
for(NSString *string in array)
{
NSlog(@“I found %@“,string);
}
5.2.4 使用代码块
最新版本的苹果编译器(基于Clang和LLVM项目)为纯C语言添加了一个叫做代码块(block)的特性。为了支持代码块功能,苹果公司添加了一个能在NSArray中通过代码块枚举对象的方法,代码如下所示:
-(void)enumerateObjectsUsingBlock:(void(^)(id obj, NSUInteger idx, BOOL *stop)) block;
使用代码块代替快速枚举,可以让循环操作并发执行。而通过快速枚举,执行操作需要一项一项线性执行。
使用:
[array enumerateObjectsUsingBlock:^(NSString *string, NSUInteger index, BOOL *stop){
NSLog(@“I found %@“,string);
}];
5.3 NSDictionary
字典(也被成为散列表或关联数组)使用的是键查询的优化方式,它可以立即找出要查询的数据,而不需要遍历整个数组。对于频繁的查询和大型的数据集来说,使用字典比使用数组快速的多。
5.3.1创建
+(id)dictionaryWithObjectsAndKeys:(id)firstObject, … ;
使用:
NSDictionary *tires = [NSDictionary dictionaryWithObjectAndKeys:
t1, @"front-left",
t2, @"front-right",
t3, @"back-left",
t4, @"back-right",
nil];
也可以使用:
NSDictionary *tires = @{@“front-left”:t1, @“front-right”:t2, @“back-left”:t3, @“back-right”:t4,nil};
5.3.2查询
-(id)objectForKey:(id)aKey;
或者是
tires[key];
使用:
Tire *tire = [tires objectForKey:@“back-right”];
或者
Tire *tire = tires[@“back-right”];
5.4 NSMutableDictionary
创建可变字典:
+ (id) dictionaryWIthCapacity: (unsigned int) numItems;
为字典添加元素:
- (void) setObject: (id) object forKey: (id) key;
删除元素:
- (void) removeObjectForKey: (id) key;
6 其他数值
NSArray和NSDictionary只能存储对象,而不能直接存储任何基本数据类型。可以使用NSInteger和NSUInteger对象来处理基本类型,然后放入NSArray或NSDictionary中。
6.1 NSNumber
Cocoa提供了NSNumber类来封装(wrap,即以对象形式来实现)基本数据类型。
6.1.1创建NSNumber对象
+(NSNumber *)numberWithChar:(char)value;
+(NSNumber *)numberWithInt:(int)value;
+(NSNumber *)numberWithFloat:(float)value;
+(NSNumber *)numberWithBool:(BOOL)value;
……
使用字面量语法创建:
NSNumber *number ;
num = @“X”;//字符型
num = @“12345”;//整型
num = @“12345ul”;//无符号长整型
num = @“12345ll”;//long long
num = @“123.4f”;//浮点型
num = @“123.45”;//双浮点型
num = @“YES”;//布尔型
NSNumber类型转换为其他类型数据:
-(Char)charValue;
-(int)intValue;
-(float)floatValue;
-(BOOL)boolValue;
-(NSString *)stringValue;
装箱:通常将一个基本类型的数据封装成对象的过程被称为“装箱”(boxing)。
开箱:从对象中提取基本类型的数据叫做开箱(unboxing)。
Objective-C语言不支持自动装箱功能。
6.2 NSValue
NSNumber实际上是NSValue的子类,NSValue可以封装任意值。可以使用NSValue将结构体放入NSArray或者NSDictionary中。
6.2.1创建NSValue对象
+ (NSValue *)valueWithBytes:(const void *)value objCType:(const char *)type;
传递的参数是你想要封装的数值的
地址(如一个NSSize或者你自己的struct)。
例如,把NSRect放入NSArray中:
NSRect rect = NSMakeRect(1,2,30,45);
NSValue *value = [NSValue valueWithBytes:&rect objCType:@encode(NSRect)];//@encode编译器指令可以接收数据类型的名称并生成合适的字符串
[array addObject:value];
使用getValue:来提取数值:
-(void)getValue:(void *)buffer;
value = [array objectAtIndex:0];
[value getValue:&rect];//参数:这个数值的变量地址
Cocoa提供了将常用的struct转换成NSValue的便捷方法:
+(NSValue *)valueWithPoint:(NSPoint)aPoint;
+(NSValue *)valueWithSize:(NSSize)size;
+(NSValue *)valueWithRect:(NSRect)rect;
-(NSPoint)pointValue;
-(NSSize)sizeValue;
-(NSRect)rectValue;
6.2 NSNull
NSNull 只有一个方法:+(NSNull *)null;
添加到集合中:
[contact setObject:[NSNull null] forKey:@“home fax machine”];
访问:
id homefax = [contact obejctForKey:@“home fax machine”];
if(home fax == [NSNull null])
{
//一些操作
}