OC中的类分为可变和不可变。下表列出了Foundation框架中主要的可变类和不可变类:
种类
不可变类
可变类
数组
NSArray
NSMutableArray
数据
NSData
NSMutableData
词典
NSDictionary
NSMutableDictionary
集合
NSSet
NSMutableSet
字符串
NSString
NSMutableString
带属性的字符串
NSAttributedString
NSMutableAttributedString
字符集合
NSCharacterSet
NSMutableCharacterSet
索引集合
NSIndexSet
NSMutableIndexSet
可变对象的生成:
可变类是不可变类的子类,所以可变类的实例对象可直接作为不可变类的实例对象。与此相反,如果想把不可变类的实例对象作为可变类的实例对象来使用的话,可以使用mutableCopy方法位不可变对象创建一个可变的副本。
- (id)mutableCopy
字符串类NSString
常量字符串:
NSString*name =@"chenzhen”;
使用这种方式定义的字符串是常量对象,可被作为NSString的对象使用。既可以做消息的参数,又可以做消息的接收者。
@“”表示空字符串,但和nil有区别。
编译器编译时会把用空格分割的字符串连在一起:
NSString*name =@"chen"@" "@"zhen”;
字符串常量从程序的执行开始到终止一直存在,调用release或者垃圾回收都不能释放字符串常量。
NSString:
NSString和NSMutableString的实例称为字符串对象或者字符串。字符串对象内部使用Unicode编码。
将字符串作为对象来处理的优点:
可以统一很多的操作
生成释放的逻辑相同
NSString还定义了很大常用的方法
由于NSString是以类簇的方式实现的,因此不能用常用的方法来为NSString定义子类。
在初始化方法的说明中,使用alloc和init的组合生成并返回实例的类方法都被标记为了便利构造函数。下面对NSString的主要方法进行说明:
(1)操作Unicode编码的字符串
NSString中的汉字都是用Unicode来表示的。Unicode的UTF-8编码兼容ASCII的7bit编码,字符串中只含有ASCII的7bit范围的编码情况下,ASCII的字符串可被当作UTF-8的Unicode字符串来处理,不能被当作UTF-16的字符串来处理。
- (
id)initWithUTF8String:(constchar*)bytes//从以Null结束的UTF-8编码的c字符串中复制信息,并初始化接收者。便利构造器:stringWithUTF8String:
- (
__strongconstchar*)UTF8String//返回编码为UTF,以NULL结尾的c语言字符串的指针。基于引用计数的内存管理模式下,返回的字符串会在消息接收对象被释放的同时被释放掉。垃圾回收的内存管理模式下,因为返回的是强指针,所以不会被垃圾回收。
- (NSUInteger)length
//返回字符的个数。
- (unichar)characterAtIndex:(NSUInteger)index
//返回索引为i的字符。unichar是两字节长的char,代表unicode的一个字符。
- (id)initWithCharacters:(const unichar *)characters length:(NSUInteger)length
//用characters中存储的length长的字符串来初始化并返回一个NSString对象,初始化以length为准,characters中就算包括‘\0’也不能作为终止标记。便利构造器:stringWithCharacters:length
- (void)getCharacter:(unichar *)buffer range(NSRange)aRange
//NSRange是一个表示范围的结构体,其中包括数据的首指针和数据长度。这个函数的作用就是将aRange所表示的字符串作为Unicode字符串写入缓冲区buffer,末尾不自动添加NULL,缓冲区需要足够大。
(2)编码转换
C风格或字节类型的字符串和NSString之间可以相互转换。字符串编码定义为枚举类型NSStringEncoding。
- (id)initWithCString:(constchar*)nullTerminatedCString
encoding:(NSStringEncoding)encoding
//用C风格字符串初始化一个NSString对象,字符串nullTerminatedCString要求以NULL结尾,编码为encoding。便利构造器:stringWithCString:encoding
- (__strongconstchar*)cStringUsingEncoding:(NSStringEncoding)encoding//返回消息接收对象的C风格字符串,编码由encoding指定。基于引用计数的内存管理模式下,返回的字符串会在消息接收对象被释放的同时被释放掉。垃圾回收的内存管理模式下,因为返回的是强指针,所以不会被垃圾回收。
- (id)initWithData:(NSData *)data
encoding:(NSStringEncoding)encoding
//用存储在data中的二进制数据来初始化NSString对象。
- (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
//接收消息的NSString对象的内容用encoding指定的方法编码,并将结果存储到一个NSData对象中并返回。
- (BOOL)canBeConvertedToEncoding:(NSStringEncoding)encoding//测试接收消息的NSString对象能否转换为encoding编码。使用类方法availableStringEncodings能够返回当前环境下可以用的编码方式。
-(NSString*)stringByAddingPercentEscapesUsingEncoding:(NSStringEncoding)encoding
//能够对一些特殊字符进行替换,主要被用于处理URL字符串,比如将空格替换成%20等。stringByReplacingPercentEscapesUsingEncoding:是上述方法的逆变换。
(3)生成指定格式的字符串
%@对应的参数必须是一个对象。当输出%@时(例如:NSLog(@“%@“, test)),实际上就是调用了test的description方法,返回结果存储到%@中。NSString不支持参数类型自动转换,所以要保证指定的类型和所传入的参数的类型一致。
- (id)initWithFormat:(NSString *)format ,...//根据format中指定的格式串来生成一个字符串,使用这个字符串初始化消息接收者。format中的参数用逗号分隔,格式字符串不能为空。便利构造器:stringWithFormat:
(4)NSString的比较
字符串比较时会返回一个NSComparisonResult类型的值,它是enum型的数据,共有三个值,分别为NSOrderedAscending,NSOrderedSame,NSOrderedDescending.
- (NSComparisonResult)compare:(NSString *)aString//区分大小写的比较
- (NSComparisonResult)caseInsensitiveCompare:(NSString *)aString
//不区分大小写的比较
- (NSComparisonResult)localizedStandardCompare:(NSString *)aString
//按照Mac系统的Finder的排序规则进行比较操作。
- (
BOOL
)isEqualToString:(NSString *)aString
- (
BOOL)hasPrefix:(NSString *)aString//检查字符串是否以aString开头。另外还可以使用方法commonPrefixWithString:options:来取出消息接收者和参数字符串开头部分相同的字符串。
(5)为字符串追加内容
- (NSString *)stringByAppendingString:(NSString *)aString
- (NSString *)stringByAppendingFormat:(NSString *)format
//在接收者字符串后面追加格式化字符串,字符串的具体格式又format指定,然后返回一个新的字符串。
(6)截取字符串
截取指定的字符串并返回。使用结构体NSRange来表示要截取的字符串的开始位置和长度。
- (NSString *)substringToIndex:(NSUInteger)anIndex//返回一个新的字符串,新字符串的范围是从接收者字符串的第一个字符开始到anIndex结束,anIndex不包含在内
- (NSString *)substringFromIndex:(NSUInteger)anIndex
//返回一个新的字符串,新字符串的范围是从anIndex开始一直到结尾,anIndex位置的字符也包含在内。
- (NSString *)substringWithRange:(NSRange)aRange
//返回新字符串的开始位置和长度由aRange来指定。
(7)检索和置换
- (NSRange) rangeOfString:(NSString *)aString//查找到aString则返回aString的位置和长度。如果没有找到,返回一个位置为NSNotFound,长度为0的NSRange类型的对象。
- (NSRange)lineRangeForRange:(NSRange)aRange
//返回NSRange所在行的范围。
- (NSString *)stringByReplacingCharactersInRange:(NSRange)aRange
withString:(NSString *)replacement
- (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target
withString:(NSString *)replacement
(8)大小写的处理
可以使用lowercaseString方法将字符串中所有的大写字母都转化为小写,与此相对,uppercaseString。除了这两个之外,方法capitalizedString能够将所有单词的首字母变为大写,其余字母变为小写。
(9)数值转换
方法doubleValue可把NSString类型的字符串转为double类型的数值。类似的还有floatValue,intValue,integerValue,boolValue.另外当输入的字符串首字母是Y,y,T,t中的任何一个,或者是不以0开头的数字时,方法boolValue都会返回YES。
(10)路径处理
文件的路径可用NSString来表示。Unix中使用“/”作为路径分割符。方法NSHomeDirectory()能够返回当前用户的主目录。以文件路径名@“tmp/image/cat.tif”为例。
- (NSString *)lastPathComponent//提取文件路径中最后一个组成部分,上面例子会返回“cat.tiff”。
- (NSString *)stringByAppendingPath:(NSString *)aStr
//将aStr加到现有字符串的末尾并返回,根据需要会自动追加分隔符。
- (NSString *)stringByDeletingLastPathComponent
//删除路径中最后一个组成部分,如果返回的结果不是根路径,那么最后的路径分隔符也会被删除。
- (NSString *)pathExtension
//返回文件扩展名,不包含“.”。没有扩展名返回空字符串。
- (NSString *)stringByAppendingPathExtension:(NSString *)aString
//将“.”和指定扩展名添加到现有路径的最后一个组成部分。
- (NSString *)stringByDeletingPathExtension
//删除文件扩展名,包括“.”,没有扩展名则返回原来的字符串。
- (
BOOL)isAbsolutePath//判断路径是不是一个绝对路径,如果是则返回YES。
+ (NSString *)pathWithComponents:(NSArray *)components
//使用components中的元素来构建路径,结合的时候自动添加路径分隔符”/“。想生成一个绝对路径的话,数组中的第一个元素使用@”/“。路径的最后想要以路径分隔符结尾的话,数组的最后一个元素使用空字符串@”“。
- (NSArray *)pathComponents
//和pathWithComponents:正好相反。
- (NSString *)stringByExpandingTildeInPath
//如果路径的第一个字符是代字符(以~开头的,例如:~/),则返回用户主目录的路径字符串。否则,直接返回输入的字符串。stringByAbbreviatingWithTildeInPath的功能正好相反,会把标准格式的字符串转换为使用代字符的字符串。
- (
__strongconstchar*)fileSystemRepresentation//返回路径的C风格字符串,使用当前系统编码。
(11)文件的输入和输出
- (
id
)initWithContentsOfFile:(NSString *)path
encoding:(NSStringEncoding)enc
error:(NSError **)error
//通过读取文件path中的内容来初始化一个NSString,文件的编码为enc。读取文件失败会释放调用者,并在返回nil的同时将详细的错误信息设定到error。便利构造器:stringWithContentsOfFile:encoding:error:
- (
id
)initWithContentsOfFile:(NSString *)path
usedEncoding:(NSStringEncoding *)enc
error:(NSError **)error
//和上一个方法不同的地方在于这个函数能够自动判别文件的编码,并通过enc返回。文件的编码是通过文件的内容和扩展属性来判断的。便利构造器:stringWithContentsOfFile:usedEncoding:error:
- (
BOOL
)writeToFile:(NSString *)path
atomically:(
BOOL
)useAuxiliaryFile
encoding:(NSStringEncoding)enc
error:(NSError **)error
//用于将字符串的内容写入到path为路径的文件中,写入的时候使用enc指定的编码,写入成功则返回YES。useAuxiliaryFile为YES的情况下,会首先新建一个临时文件,把字符串的内容写入到临时文件中。然后再在写入成功后把临时文件重命名为path指定的文件。这种方法写入发生错误时不会损坏原来的文件。为NO时,则直接将字符串内容输入到path指定的文件中。如果写入失败,则会在返回NO的同时把出错的原因写入到error中,并返回给函数调用者。
(12)其他
- (id)init//对接收者进行初始化,并返回一个空字符串。通常被用于NSMutableString的初始化。便利构造器:string。
- (
id)initWithString:(NSString *)aString//返回一个字符串对象,其内容是aString的副本。aString也可以是NSMutableString的实例对象。用这个方法可以用一个可变的字符串对象生成一个不可变的字符串对象。便利构造器:stringWithString:
- (NSString *)description
//返回消息接收者内容的字符串。NSString的description方法会直接返回self。
- (
id)propertyList//返回消息接收者的属性列表。
- (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)sep
//用参数sep指定的字符集合中的字符作为分隔符,对消息接收者字符串进行分割,并返回分割后生成的字符串数组。
NSMutableString:
NSMutableString是NSString的子类,所以可以使用NSString中定义的所有方法。下面对NSString中未定义的方法进行说明:
(1)实例对象的生成和初始化
- (id)initWithCapacity:(NSUInteger)capacity//初始化一个NSMutableString类型的对象,capacity指明了要被初始化的NSMutableString对象的大小.NSMutableString的对象会随着字符串的变化而自动扩展内存,所以capacity不需要非常精密。除了这个方法之外,还可以使用NSString的init方法或NSString的类方法string:来生成一个空的NSMutableString对象。便利构造器:stringWithCapacity:
(2)追加字符串
- (void)appendString:(NSString *)aString//在消息接收者的末尾追加aString。
- (
void)appendFormat:(NSString *)format,……//在消息接收者的末尾遍加format格式的格式化字符串。
(3)插入删除置换
- (void
)insertString:(NSString *)aString
atIndex:(NSUInteger)loc
//在消息接收者的atlndex位置插人字符串aString。
- (
void)deleteCharactersInRange:(NSRange)range//结构体NSRange表示一个范围,其中包含了开始位置和长度,这个方法的作用是从接收者中删除aRange指定范围内的字符串。
- (
void)setString:(NSString *)aString//复制aString指定的字符串,并将其设置为消息接收者的内容。
- (
void
)replaceCharactersInRange:(NSRange)aRange
withString:(NSString *)aString
//把aRange指定范围内的字符内容替换为aString指定的字符串。
- (NSUInteger)replaceOccurrencesOfString:(NSString *)target
withString:(NSString *) replacement.
options:(NSStringCompareOptions)opts
range:(NSRange)searchRange
//searchRange指定范围内如果存在字符串target,就将其替换为replacement。这个函数的返回值就是替换的次数。使用选项opts可以设置忽略大小写,或者使用正则表达式进行替换等。
NSData
NSData:
NSData是Cocoa下对二进制数据的一个封装,能够把二进制数据当作对象来处理。
同C语言的数组相比,NSData的优点是可以进行更抽象话的操作,使内存管理更容易,同时也是cocoaAPI中操作二进制数据的标准。
NSData是不可变的,所以实例对象一旦创建之后就不可改变其内容。而如果想改变数据的内容,就需要使用将在后面介绍的类NSMutableData。NSData和NSMutableData的实例对象有时也称为数据对象。
NSData的接口文件定义在Foundation/NSData.h中。NSData是以类族的方式实现的,所以不能用通常的方法来为NSData定义子类下面介绍了类NSData的几个主要方法,如果想了解全部方法,请参考苹果公司的文档。
(1)数据对象的生成和初始化
- (id)initWithBytes:(constvoid*)bytes length:(NSUInteger)length//复制以bytes开头、长度为length的数据,进行初始化使其成为数据对象的内容。便利构造器:dataWithBytes:length:
- (id)initWithBytesNoCopy:(void*)bytes length:(unsigned)length freeWhenDone:(BOOL)flag;//将以bytes开头、长度为length的数据初始化为数据对象的内容。生成的NSData中保存的是指向数据的指针,并没有对数据进行复制操作。flag为YES的时候,生成的NSData对象是bytes的所有者,当NSDate对象被释放的时候也会同时释放bytes,所以bytes必须是通过malloc在堆上分配的内存。当flag为NO的时候,bytes不会被自动释放,释放bytes时要注意时机,不要在NSData对象还被使用的时候释放bytes。便利构造器:datawithBytesNoCopy:length:freeWhenDone:
- (id)initWithData:(NSData *)data//用指定的NSData对象aData来创建一个新的NSData对象。参数可以是NSMutableData对象,所以用这个方法可以为一个可变的NSMutableData对象生成一个不可变的NSData对象。便利构造器:dataWithData:
+ (id)data//返回一个长度为0的临时NSDate对象。这个方法多被用于NSMutableData中(创建一个长度为0的NSData意义不大)。对应的初始化方法为init。
(2)访问NSData中的数据
- (NSUInteger)length//返回NSData对象中数据的长度
- (
constvoid*)bytes//返回NSData对象中数据的首指针
- (
void)getBytes:(void*)buffer length:(NSUInteger)length//复制NSData对象的数据到buffer中,复制时从NSData对象中数据的开头开始,副本的长度为length。如果想获得指定范围内的数据的话,可以使用方法getBytes:range:
- (NSData *)subdataWithRange:(NSRange)range
//用range指定范围内的data来生成一个新的NSData对象并返回。
- (NSRange)rangeOfData:(NSData *)dataToFind options:(NSDataSearchOptions)mask range:(NSRange)searchRange
//在接收者中searchRange指定的范围内,如果能找到和dataToFind一样的数据,则返回数据的位置和长度。mask是搜索时用到的选项,使用mask可以从后向前查找。dataToFind不可以为nil。
(3)比较
- (BOOL)isEqualToData:(id)anObject//两个NSData的数据长度和内容一致时返回YES
(4)文件输入和输出
可以从文件读人数据来初始化NSData对象,或者把NSData对象中的内容输出到文件。除了用NSString指定文件路径的函数外,还有使用NSURL来指定文件路径的函数。
数组类
NSArray:
数组中既可以存放同一类的对象,也可以存放不同类的对象,但不可以存放nil,nil被用于标志数组的结束。
NSArray是不可变数组,一旦创建后,就不能再添加,删除或修改其中的元素。
数组对象的所有权:
数组,集合和词典对象这些可以包含多个对象的容器被总称为集合。一个对象被放入集合时会收到retain的消息,被从集合中删除时也会收到release消息。
快速枚举:
OC2.0提供了一个用于遍历容器类的语法,叫做快速枚举。for...in语法。
集合是可变的也可以是不可变的,可变集合在循环的过程中也不允许被改变,如果集合发生了改变,就会抛出异常。
遍历容器中元素的顺序和容器的类型有关。如果是数组,就会从头开始遍历,而如果是集合或是词典类型,遍历的顺序则和容器的内部实现有关。
变量可以在for的条件中定义,这种情况下变量只在for...in语法块内有效。
枚举器NSEnumerator:
枚举器是一个用来遍历集合类中的元素对象的抽象类。枚举器没有创建实例的公有接口,不能给枚举器发送alloc消息。使用枚举器遍历一个集合对象的同时,如果向该集合对象增加或删除对象,就可能会导致不可预期的结果,是很危险的。
基于引用计数管理模式下,在通过枚举器遍历集合对象的时候,枚举器对象拥有这个集合对象的所有权,取出最后一个元素之后,它就会自动放弃对这个集合对象的所有权。同时,因为枚举器是一个临时对象,所以当其所在的自动释放池被释放的时候,该枚举器也会被释放掉。
快速枚举和枚举器:
快速枚举和枚举器在遍历过程中,都不能改变集合中的元素。如果在遍历过程中想要更改集合对象的话,可以使用下标来循环遍历。如果要删除集合中的某个元素,需要从后向前遍历。
快速枚举内部用c语言实现,速度快。
for...in语法可以将in后的“集合”换为“枚举器”。
集合类:
它是一组单值对象的集合,NSSet是无序的,同一个对象只能保存一个。
NSMutableSet有一个子类NSCountedSet,是一个可变的集合类,能后统计集合中对象的个数,这个类中可以存放多个相同值的对象。
词典类
词典中的数据以键值对的形式保存,一个键值对称为entry。键和值可以是除nil以外的任何对象,一般使用字符串作为键。键是关键字。
value由多个字符串构成的时候可以用()把他们括起来,这种情况下词典对象的值就相当于一个数组对象。
词典的键必须是唯一的。
词典对象的值可以用NSNull来表明一个词典对象为空。
一个对象作为词典的key或者value时,词典中存放的是这个对象的一份副本。
NSDictionary:
不可变,一旦创建就只能查询,不可在增加,删除,或修改其中的内容。
包裹类
Cocoa Foundation 框架的集合类中只可以放入对象,不能存储基本类型的数据。所以Cocoa提供了NSNumber类来包装char,int,long等基本类型的数据。像结构体,指针这类复杂的数据类型,NSNumber没有办法把他们存储为对象,这时就可以使用NSValue。NSValue是NSNumber的父类,NSValue可以把任意对象包装成对象。NSNull是为了把nil放入集合类中而定义的包裹类。
注意:NSInteger不是一个对象,而是基本的数据类型的typedef。
NSValue:
接口定义在Foundation/NSValue.h中,坐标等结构体定义在Foundation/NSGeometry.h中。
类型编码和@encode()
OC的数据类型甚至自定义类型,都可以使用ASCII编码的类型描述字符串来表示。@encode()可以返回给定数据类型的类型描述字符串。例如:@encode(int)返回“i”。
下面是一个为结构体创建NSValue实例的例子:
struct
grid {
int
x, y;
double
weight;
};
structgridfoo, bar;id
obj;
//对结构体foo进行封装并返回一个对象obj的代码
obj = [[NSValue alloc] initWithBytes:&foo objCType:
@encode(struct
grid)];
//把数据从obj中读入到变量bar中
[obj getValue:&bar];
NSValue只能包装长度确定的数据,例如,NSValue不能包装一个C风格的字符串。
NSValue和NSNumber是以类簇的形式实现的,所以无法用通常的方法为其定义子类。
NSNull
nil不能放在数组或字典中,因为nil在它们中有特殊的含义,但有时我们确实需要一个特殊的对象表示空值。
NSURL
关于URL:
统一资源定位符。除用于因特网之外,也可以用于表示本机资源。除HTTP协议外,其他协议也可以使用URL来访问资源。
Mac OS X 和iOS中规定了四种可以使用NSURL来访问资源的形式:
http:超文本链接协议
https:超文本传输安全协议http的安全版本,是超文本传输协议和SSL/TLS的组合
ftp:文件传输协议
file:访问某台主机上的文件
访问某个资源的写法如下:
协议名://主机名/主机内资源的路径
操作URL的时候应该使用专用的NSURL类,而不要把URL当作字符串来手工解析。
将string作为返回值的情况下,一定要经过url编码的字符串。方法名中如果包含了string,那么世纪传入的参数也一定是经过编码的。另一方面,path用于表示URL的路径,无论作为返回值还是参数都要返回为编码的字符串。