Objective-C学习笔记

所谓的框架式由许多类/方法/函数/文档按照一定的逻辑组织起来的集合,以便使研发程序变得更容易,

Mac下大约有90多个框架,而为所有的程序开发奠定基础的框架称为Foundation框架,他允许使用一些

基本对象,包括:数字/字符串/集合/日期/内存/文件/存储/几何;ApplicationKit框架用来开发交互式

图形应用程序;通常所有的两个术语:

1.Cocoa:Foundation/CoreData/ApplicationKit

2.CocoaTouch:Foundation/CoreData/UIKit

二.数字/字符串/集合

1.数字对象:NSNumber,他可以把基本数据类型打包成对象,进而可以向他们发送消息,对于每种基本数据

类型,类方法都能为它创建一个NSNumber对象,并设置为指定的值,这些方法以numberWithXXX开头,紧接数据

的类型;此外,可以使用实例方法将以前创建的NSNumber对象设置为指定的值,这些都是以initWithXXX开头的;

相应获取基本数据的接口为XXXValue;并提供isEqualToNumber和compare方法来进行数字对象的比较。

2.字符对象:NSString/NSMutableString,以@开头的unichar字符组成的字符串;NSLog格式字符%@不仅可以显示

NSString对象,而且还可以显示其他对象;事实上,通过覆盖继承的description方法,还可使用这些格式字符显示

你自己的类对象,如果不覆盖,NSLog仅仅显示类名和该对象在内存中的地址;注意NSRange不是一个对象,而是一个

结构,可以通过NSMakeRange方法生成;NSString是不能改变的,如果要改变可以使用他的子类NSMutableString,称

为可变字符,综上所述,该类有、以下几个类型的API:创建及初始化/判断和比较/大小写转换/截取/转换类型/对文

件的处理/可变字符/其他。

3.数组对象:NSArray/NSMutableArray,就像存在可变字符串和不可变字符串,同样也存在可变数组和不可变数组;

有以下几个类型的API:创建及初始化/数组元素的操作/可变数组;需要注意的的是基本类型必须转成NSNumber,结构体

必须转成NSValue,才能进行操作,并且如果使用复杂的运算法则操纵大型数字数组,采用C语言提供的低级数组构造执行

这种任务可能更加有效。self.name=theName等价于[self setName:theName],他会使用setter方法为实例变量赋值;与此

不同的是,name=theName的写法绕过了setter方法,直接为实例变量赋了参数的值;故推荐采用前者来增加一层抽象性。

在使用比较的过程中,会使用NSComparisonResult类型的值,他提供以下几种选择: NSOrderedAscending/NSOrderedSame/

NSOrderedDescending。

注意:对于CGPoint/CGSize/CGRect/NSRange这种常用的结果用,需要借组NSValue的valueWithXXX方法来wrapping成对象,

并利用XXXValue来unwrapping成结构体

4.字典对象:NSDictionary/NSMutableDictionary,存在可变字典和不可变字典,他们都是所谓的由键-对象对组成的数据集合,

词典中的键必须是单值得,通常他们是字符串,但也可以是其他对象类型。有以下几个类型的API:创建及初始化/访问键值/

文件处理/可变字典/其他。

5.集合对象:NSSet/NSMutableSet/NSIndexSet/NSCountedSet,他是一组单值对象集合,可以使可变的,也可以使不变的,有以下

几个类型的API:创建及初始化/访问元素/判断比较/可变集合。比较特别的是NSIndexSet,他用于存储有序的索引到某种数据结构,

比如数组的indexesOfObjectsPassingTest方法,会接受一个传递数组元素/索引号/BOOL变量指针的区块,返回NSIndexSet代表包含

数组中满足条件的所有元素的索引。他有以下几个对象实例方法:containIndex/firstIndex/lastIndex/indexLessThanIndex/

indexesPassingTest。

三.文件管理

利用NSFileManager和NSFileHandle提供以下几种API:文件与目录的操作/获取文件盒目录信息/判断文件/文件读取/目录工具函数:

1.NSFileHandle:可以打开文件并对文件执行多次读/写操作

2.NSURL:利用其类方法URLWithString生成后,允许在应用中使用URL方法,此后就可以用URL的内容了,

包括stringWithContentsOfURL/dictionaryWithContentsOfURL/arrayWithContentsOfURL/dataWithContentsOfURL

3.NSBundle:允许在应用中使用包的方法

/代表根目录;~代表用户主目录;.代表当前目录;..代表父目录;在使用文件时,需要频繁地将

4.NSData/NSMutableData:允许用来设置缓冲区,将文件的内容读入缓冲区,或将缓冲区的内容写到文件中

5.NSDirectoryEnumerator:可以采用他来遍历Directory,例如

BOOL flag;

NSFileManager* fm = [NSFileManager defaultManager];

NSString* path = [fm currentDirectoryPath];

NSDirectoryEnumerator* dirEnum = [fm enumeratorAtPath:path];

while((path=[dirEnum nextObject]) != nil)

{

[fm fileExistsAtPath:path isDirectory:&flag];

if(flag == YES)

[dirEnum skipDescenedents];

}

6.使用NSPathUtilities.h的辅助函数来操作文件系统

7.常用的目录

1).Documents(NSDocumentDirectory):写入应用相关数据文件的目录,iTunes会看到,还可以备份到云端

2).Libray/Caches(NSCachesDirectory):写入应用支持文件的目录,iTunes不会看到,也不会备份到云端

3).tmp(NSTemporaryDirector):存放临时文件,程序终止的时候要移除他

4).Library/Preferences:程序的偏好设置文件,使用NSUserDefaults来创建/读取/修改

8.NSProcessInfo:允许你设置或检索正在运行的应用程序的各种类型的信息

注:FileHandle类并没有提供创建文件的功能,必须使用FileManager方法来创建文件,因此他相关的Writing/

Reading/Updating的API都假定文件已经存在,否则返回nil

9.NSBundle:当创建一个应用时,系统存储了应用相关的所有数据,并将这些内容放入一个称为application

bundle中,这个类就为了访问这些资源而生,他提供以下几个方法:

1).mainBundle:应用包所在目录

2).pathForResource:ofType:列出该目录指定的文件并返回文件的路径,随后可以用stringWithContentsOfFile

来将文件读取到程序中

3).pathsForResourcesOfType:inDirectory:列初指定目录下相应后缀名的文件列表

四.内存管理

提供给Objective-C程序的基本内存管理模型有以下三种:

1.自动垃圾收集:当内存到低位时,开始清理,是一个计算密集的过程,仅仅Mac支持

2.手工引用计数和自动释放池:前者利用retain/release计数机制,后者利用NSAutoreleasePool/drain机制,

在该环境下,可以为属性添加atomic/nonatomic,assign/retain/copy特性;对使用了retain/copy/mutableCopy/

alloc/new方法的任何对象,以及具有retain/copy特性的属性进行释放,需要覆盖dealloc方法,使得在对象被释放

的时候能释放这些实例变量

3.自动引用计数(ARC):内部维护引用计数,系统会检测何时需要保持对象和释放对象,编译器会管理好对象的内存,

通过生成正确的代码区自动释放或保持返回的对象

1)强变量:

当给变量赋值的时候,新的retain,旧的release,然后把新的assign给旧的,如果使用ARC,需要使用__strong关键字,

或者为属性添加strong特性,默认是unsafe_unretained(assign)

2)弱变量:

当两个对象都持有彼此的强引用时,将会产生循环保持(retain cycle),解决这个问题可以弱引用,需要使用__weak

关键字,或者为属性添加weak特性,需要注意的是,iOS4和Mac10.6中不支持弱变量

3)@autoreleasepool块

在main中,有一个大块,会在应用程序结束的时候进行清理,如果在局部创建,可以再内部进行块的嵌套

五.复制对象:

通过实现一个符号<NSCopying>协议的方法来制作副本,如果类必须区分要产生对象的是可变副本还是不可变副本,

还需要根据<NSMutableCopying>协议实现一个方法,即copy和mutableCopy方法;如果是自己编写的类,可以要支持

copy方法就需要实现<NSCopying>协议,进而实现copyWithZone方法,在该方法中,参数zone的类型为NSZone,他与不

同的存储区有关,你可以在程序中分配并使用这些存储区。只有在编写要分配大量内存的应用程序并且想要通过将空间

分配分组到这些存储区来优化内存分配时,才想要处理这些zone参数,可以使用传递给allocWithZone的内存分配方法,

在指定的存储区中分配内存;如果结合属性一起使用,想要添加copy的特征。

六.归档:

1.使用XML属性列表进行归档

可以使用XML属性列表(plists)存储诸如默认参数选择、应用程序设和配置信息这样的数据;特别的是如果对象是

NSString、NSDictionary、NSArray、NSData或NSNumber,就可以使用对象方法writeToFile:atomically将数据写到

文件中;打开的时候就可以利用类方法XXXWithContentsOfFile将文件传入以相应的内容来创建对象;需要注意的是

如果想在程序中使用属性列表,可以查看NSPropertyListSerialization类。

2.使用NSKeyedArchiver归档

使用它可以写入除字符串、数组和字典外的其他类型,他提供了一个类方法archiveRootObject:toFile来序列化;

反之,利用类方法unarchiveObjectWithFile来反序列化;此时,如果操作一个非自带的对象,就会报错,除非你

按照<NSCoding>协议,来实现encodeWithCoder和initWithCoder;需要注意的是对象调用encodeObject:forKey和

decodeObjectforKey来完成(如果是非内置对象就会调用到encodeWithCoder/initWithCoder),基本数据类型调用

encodeXXX:forKey和decodeXXXforKey。

3.使用NSData归档

首先创建NSMutableData对象,并在创建NSKeyedArchiver对象之后,以data对象为参数调用initForWritingWithMutableData,

获得archiver,此时,就可以向存储在archiver中的对象发送编码信息,实际上,所有的编码信息在收到finishEncoding消息

之前都被归档在指定的数据空间内,最后再调用NSData的方法writeToFile:atomically将数据写入文件。

4.使用归档程序复制对象

dataArray2 = [NSKeyedUnarchiver unarchiveObjectWithData:

[NSKeyedArchiver archiverdDataWithRootObject : dataArray]];