本章主要介绍Objective-C输入/输出(简称I/O或O/I)的相关知识。
Objective-C提供了如下相关API:
本章包括:
NSFileManager进行管理文件和目录,包括创建、删除、移动、修改和复制文件。
NSFileHandle进行处理读取文件内容,
NSUrl进行读取网络资源;
NSBundle进行读取项目内部资源;
Foundation提供了NSData和NSMutableData,他们代表Objective-C的数据缓冲区。NSData的作用有两个:
NSData的初始化方法:
得到NSData对象之后,可以调用如下方法来访问数据:
例如:
(1)、使用指定URL对应的数据初始化NSData
//使用NSData读取指定URL对应的数据
NSData* data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://www.crazyit.org/ethos.php"]];
(2)、求得NSData的长度
NSLog(@"%ld",[data length]);//
//定义一个长度为100的数组
char buffer[100];
(3)、将指定范围的数据写入数组
//将NSData指定范围的数据写入数组
[data getBytes:buffer range:NSMakeRange(103, 100)];
//输出数组的内容
NSLog(@"%s",buffer);
/*
输出:
transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-T…
*/
(4)、将NSData转化成NSString
//直接将NSData的数据用UTF-8的格式转化成字符串
NSString* content = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"网页内容为:%@",content);
NSFileManager代表文件管理器,通过NSFileManager的帮助,开发者可以完成许多通用的文件操作。当开发者使用NSFileManager执行移动、复制、链接、删除文件或目录时,程序可以为NSFileManager提供一个配套的事件委托(实现了NSFileManagerDelegate协议的对象)。
NSFileManager采用文件作为文件的唯一标识,每个文件都是一个普通的NSString对象,它即可使用相对路径,也可以是绝对路径。
除此之外,还有几个比较特殊的路径:
NSFileManager为访问文件属性和内容提供了如下方法:
例如:
(1)、获取单例
//单例
NSFileManager* fm = [NSFileManager defaultManager];
(2)、是否存在
//将输出代表真的1
NSLog(@"mydict.txt是否存在:%d",[fm fileExistsAtPath:@"mydict.txt"]);//mydict.txt是否存在:1
(3)、是否存在且是否为目录
BOOL isDir;
NSLog(@"mydict.txt是否存在:%d",[fm fileExistsAtPath:@"mydict.txt" isDirectory:&isDir]);
//将会输出代表假的0
NSLog(@"mydict.txt是否为目录:%d",isDir);//mydict.txt是否为目录:0
(4)、是否可读
//将会输出代表真的1
NSLog(@"mydict.txt是否为可读文件:%d",[fm isReadableFileAtPath:@"mydict.txt"]);
(5)、是否可写
//将会输出代表真的1
NSLog(@"mydict.txt是否为可写文件:%d",[fm isWritableFileAtPath:@"mydict.txt"]);
(6)、是否可执行
//将会输出代表假的0
NSLog(@"mydict.txt是否为可执行文件:%d",[fm isExecutableFileAtPath:@"mydict.txt"]);
(7)、是否可删除
//将会输出代表真的1
NSLog(@"mydict.txt是否为可删除文件:%d",[fm isDeletableFileAtPath:@"mydict.txt"]);
(8)、获取路径组件
//获取mydict.txt文件所在的路径组件
NSArray* arrat = [fm componentsToDisplayForPath:@"mydict.txt"];
NSLog(@"--mydict.txt所在路径的完整路径组件为--");
for (NSObject* ele in arrat) {
NSLog(@"%@",ele);
/* 输出: Macintosh HD 用户 chenxiao 资源库 Developer Xcode DerivedData 重新学习-fvftebswkwfhovfdqhoyfjkqitbx Build Products Debug mydict.txt */
}
(9)、获取相关属性
//获取文件的相关属性
NSDictionary* attr = [fm attributesOfItemAtPath:@"mydict.txt" error:nil];
//获取文件属性的详情
NSLog(@"mydict.txt的创建时间为:%@",[attr fileCreationDate]);//mydict.txt的创建时间为:2014-12-08 07:37:03 +0000
NSLog(@"mydict.txt的属主账户为:%@",[attr fileOwnerAccountName]);//mydict.txt的属主账户为:chenxiao
NSLog(@"mydict.txt的文件大小为:%lld",[attr fileSize]);//mydict.txt的文件大小为:356
(10)、获取文件内容
//直接获取文件内容
NSData* data = [fm contentsAtPath:@"mydict.txt"];
//直接将NSData的数据用UTF-8的格式转换字符串
NSString* content = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"------输出文件内容------");
NSLog(@"%@",content);
/*
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>four</key>
<string>Perl</string>
<key>one</key>
<string>Objective-C</string>
<key>three</key>
<string>Python</string>
<key>two</key>
<string>Ruby</string>
</dict>
</plist>
*/
NSFileManager为创建、删除、移动、复制文件或目录提供了如下方法:
例如:注意路径全是绝对路径
(1)、单例
NSFileManager* fm = [NSFileManager defaultManager];
(2)、创建目录
//创建目录
//第一个参数:文件路径
//第二个参数:如果父目录不存在,则创建父目录
//第三个参数:文件属性
[fm createDirectoryAtPath:@"/Users/chenxiao/Desktop/xyz/abc" withIntermediateDirectories:YES attributes:nil error:nil];
NSString* content = @"《疯狂iOS讲义》是我正在学习的图书";
(3)、创建文件
//创建一个文件
[fm createFileAtPath:@"/Users/chenxiao/Desktop/xyz/abc/myInfo.txt" contents:[content dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];
(4)、获取文件属性
//获取文件属性
NSLog(@"myInfo.txt:%@",[fm attributesOfItemAtPath:@"/Users/chenxiao/Desktop/xyz/abc/myInfo.txt" error:nil]);
/*
输出:
myInfo.txt:
{
NSFileCreationDate = "2014-12-09 09:51:54 +0000";
NSFileExtensionHidden = 0;
NSFileGroupOwnerAccountID = 20;
NSFileGroupOwnerAccountName = staff;
NSFileHFSCreatorCode = 0;
NSFileHFSTypeCode = 0;
NSFileModificationDate = "2014-12-09 09:51:54 +0000";
NSFileOwnerAccountID = 501;
NSFileOwnerAccountName = chenxiao;
NSFilePosixPermissions = 420;
NSFileReferenceCount = 1;
NSFileSize = 48;
NSFileSystemFileNumber = 6150933;
NSFileSystemNumber = 16777219;
NSFileType = NSFileTypeRegular;
}
*/
(5)、复制文件
//复制一份新文件
[fm copyItemAtPath:@"myInfo.txt" toPath:@"/Users/chenxiao/Desktop/xyz/abc/copyInfo.txt" error:nil];
(6)、删除文件
//删除文件
[fm removeItemAtPath:@"/Users/chenxiao/Desktop/xyz/abc/myInfo.txt" error:nil];
(7)、删除目录
//删除目录
[fm removeItemAtPath:@"/Users/chenxiao/Desktop/xyz" error:nil];
对于文件目录,NSFileManager提供了如下方法查看目录包含的内容
例如:
(1)、单例
NSFileManager* fm = [NSFileManager defaultManager];
(2)、获取指定目录下的文件夹 不递归子目录
//获取指定目录下的所有文件和文件夹
NSArray* array = [fm contentsOfDirectoryAtPath:@"/Users/chenxiao/Desktop/重新学习" error:nil];
for (NSString* item in array) {
NSLog(@"%@",item);
/* .DS_Store .git FDPersonTest.h FKPerson.h FKPerson.m FKPersonTest.m 重新学习 重新学习.xcodeproj */
}
(2)、获取指定目录下所有文件和文件夹的枚举器 递归子目录
//获取指定目录下所有文件和文件夹对应的枚举器
NSDirectoryEnumerator* dirEnum = [fm enumeratorAtPath:@"/Users/chenxiao/Desktop/重新学习"];
NSString* file;
while (file = [dirEnum nextObject]) {
//如果该文件名以.m结尾
if ([[file pathExtension] isEqualToString:@"m"]) {
//直接获取文件内容
NSData* data = [fm contentsAtPath:[NSString stringWithFormat:@"/Users/chenxiao/Desktop/重新学习/%@",file]];
//直接将NSData的数据用UTF-8的格式转换字符串
NSString* content = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"content = %@",content);
}else{
NSLog(@"%@",file);
}
}
(3)、获取目录下的所有子目录,递归子目录
//获取当前目录下的所有子目录
NSArray* subArr = [fm subpathsOfDirectoryAtPath:@"/Users/chenxiao/Desktop/重新学习" error:nil];
NSArray* subarr = [fm subpathsAtPath:@"/Users/chenxiao/Desktop/重新学习"];
NSLog(@"%@==%@",subArr,subarr);
NSPathUtilities.h包含了对NSString类的扩展,从而为NSString类新增了一些专门用于操作路径的方法:
例如:
(1)、获取当前用户
NSLog(@"当前用户名为:%@",NSUserName());//当前用户名为:chenxiao
(2)、获取当前用户完整用户名
NSLog(@"当前用户的完整用户名为:%@",NSFullUserName());//当前用户的完整用户名为:陈晓
(3)、获取当前用户的home目录
NSLog(@"当前用户的home目录为:%@",NSHomeDirectory());//当前用户的home目录为:/Users/chenxiao
(4)、获取root用户的home目录
NSLog(@"root用户的home目录为:%@",NSHomeDirectoryForUser(@"root"));//root用户的home目录为:/var/root
(5)、获取系统临时目录
NSLog(@"系统临时目录为:%@",NSTemporaryDirectory());//系统临时目录为:/var/folders/js/fsgm7wns4tq37pc2cfdqsp9w0000gn/T/
(6)、将~root解析成root用户的的home目录
NSString* path1 = @"~root";
//将~root解析成root用户的home目录
NSLog(@"解析~root的结果:%@",[path1 stringByExpandingTildeInPath]); //解析~root的结果:/var/root
(7)、替换成~的形式
NSString* path2 = @"/Users/chenxiao/publish";
//将会输出~/publish
NSLog(@"替换成~的形式:%@",[path2 stringByAbbreviatingWithTildeInPath]);//替换成~的形式:~/publish
(8)、遍历路径中包含的个路径组件
//遍历该路径中包含的各路径组件
NSArray* array = [path2 pathComponents];
for (NSString* item in array) {
NSLog(@"%@",item);
/* 输出: / Users chenxiao publish */
}
(9)、在路径后边追加一个路径
//在path2路径后追加一个路径
NSString* path3 = [path2 stringByAppendingPathComponent:@"abc.m"];
NSLog(@"path3为:%@",path3);//path3为:/Users/chenxiao/publish/abc.m
(10)、获取路径的最后部分
//获取路径的最后部分
NSString* last = [path3 lastPathComponent];
NSLog(@"path3的最后一个路径组件为:%@",last);//path3的最后一个路径组件为:abc.m
(11)、获取路径的最后部分的扩展名
//获取路径的最后部分的扩展名
NSLog(@"path3的最后一个路径的扩展名:%@",[path3 pathExtension]);//path3的最后一个路径的扩展名:m
当一个程序运行起来之后就变成了一个进程,NSProcessInfo对象则可用于获取该进程的相关信息,包括获取运行该程序的参数、进程标识符等。还可以获取该进程的主机名,操作系统名,操作系统版本等信息。
程序调用NSProcessInfo的processInfo类方法即可获取该进程对应的NSProcessInfo对象,接下来即可调用NSProcessInfo的如下方法来获取该进程,以及该进程所在系统的信息:
例如:
(1)、获取当前进程的ProcessInfo对象
//获取当前进程对应的ProcessInfo对象 NSProcessInfo* proInfo = [NSProcessInfo processInfo];
(2)、获取运行该程序所指向的参数
//获取运行该程序所指向的参数
NSArray* arr = [proInfo arguments];
NSLog(@"运行程序的参数为:%@",arr);
(3)、获取进程标识符
NSLog(@"进程标识符为:%d",[proInfo processIdentifier]);//进程标识符为:1590
(4)、获取进程的进程名
NSLog(@"进程的进程名为:%@",[proInfo processName]);//进程的进程名为:重新学习
(5)、获取所在系统的主机名
NSLog(@"进程所在系统的主机名为:%@",[proInfo hostName]);//进程所在系统的主机名为:chenxiaodemacbook-pro.local
(6)、获取进程所在系统的操作系统
NSLog(@"进程所在系统的操作系统为:%ld",[proInfo operatingSystem]);//进程所在系统的操作系统为:5
(7)、获取进程所在系统的操作系统名
NSLog(@"进程所在系统的操作系统名为:%@",[proInfo operatingSystemName]);//进程所在系统的操作系统名为:NSMACHOperatingSystem
(8)、获取进程所在系统的操作系统版本字符串
NSLog(@"进程所在系统的操作系统版本字符串为:%@",[proInfo operatingSystemVersionString]);//进程所在系统的操作系统版本字符串为:Version 10.9.5 (Build 13F34)
(9)、获取进程所在系统的物理内存
NSLog(@"进程所在系统的物理内存为:%lld",[proInfo physicalMemory]);//进程所在系统的物理内存为:8589934592
(10)、获取进程所在系统的处理器数量
NSLog(@"进程所在系统的处理器数量为:%ld",[proInfo processorCount]);//进程所在系统的处理器数量为:4
(11)、获取进程所在系统的激活的处理器数量
NSLog(@"进程所在系统的激活的处理器数量为:%ld",[proInfo activeProcessorCount]);//进程所在系统的激活的处理器数量为:4
(12)、获取进程所在系统的运行时间为
NSLog(@"进程所在系统的运行时间为:%f",[proInfo systemUptime]);//进程所在系统的运行时间为:17633.546019
NSFileHandle提供了处理文件IO相关方法,步骤如下:
NSFileHandle提供的方法如下:
例如:
(1)、打开一份可读文件
//打开一份文件准备读取
NSFileHandle* fh = [NSFileHandle fileHandleForReadingAtPath:@"/Users/chenxiao/Desktop/重新学习的ios/重新学习的ios/NSFileHandleTest.m"];
NSData* data;
(2)、按指定的长度读取文件,文件指针会移动
//读取NSFileHandle中的128字节
while ([(data = [fh readDataOfLength:128]) length] > 0) { NSLog(@"%ld",[data length]); //直接将NSData的数据用UTF-8的格式转换字符串 NSString* content = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@",content); }
(3)、关闭文件
[fh closeFile];
(4)、打开一份可写文件
//打开一份可以准备写入的文件
NSFileHandle* fh2 = [NSFileHandle fileHandleForWritingAtPath:@"/Users/chenxiao/Desktop/abc.txt”];
(5)、如果文件不存在,创建文件
if (!fh2) {
//创建一个NSFileManager对象
NSFileManager* fm = [NSFileManager defaultManager];
[fm createFileAtPath:@"/Users/chenxiao/Desktop/abc.txt" contents:nil attributes:nil];
fh2 = [NSFileHandle fileHandleForWritingAtPath:@"/Users/chenxiao/Desktop/abc.txt"];
}
(6)、将指定数据写入文件
NSString* myBook = @"疯狂iOS讲义";
[fh2 writeData:[myBook dataUsingEncoding:NSUTF8StringEncoding]];
(7)、关闭文件
[fh2 closeFile];
URL(Uniform Resource Locator)对象代表同意资源定位器,它是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是对更复杂的对象引用,例如:对数据库或搜索引擎的查询。通常情况下,URL可以由协议名、主机、端口和资源路径组成,格式如下:
scheme://host:port/path
例如,如下的URL地址:
http://www.crazyit.org/index.php
例如:
(1)、创建NSURL对象
NSURL* url = [NSURL URLWithString:@"http://www.crazyit.org/index.php”];
(2)、获取NSURL对象的协议名
NSLog(@"url的协议名为:%@",[url scheme]);//url的协议名为:http
(3)、获取NSURL对象的主机
NSLog(@"url的主机为:%@",[url host]);//url的主机为:www.crazyit.org
(4)、获取NSURL对象的端口
NSLog(@"url的端口为:%@",[url port]);//url的端口为:(null)
(5)、获取NSURL对象的资源路径
NSLog(@"url的资源路径为:%@",[url path]);//url的资源路径为:/index.php
(6)、使用URL对应的资源来初始化NSString对象
//使用URL对应的资源来初始化NSString对象
NSString* homePage = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
//输出NSString内容,即可看到页面源代码
NSLog(@"%@",homePage);
得到NSBundle对象,接下来就可通过该对象的如下常用方法来获取指定的资源文件:
例如:
NSString* filePath = [[NSBundle mainBundle] pathForResource:@"bookinf" ofType:@"txt"];
//使用指定文件的内容来初始化NSString
NSString* content = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
NSLog(@"content = %@",content);
归档就是用某种格式把一个或多个对象保存到指定文件中,方便以后从文件中恢复他们。通常来说,归档包含两方面的操作:
用法如下:
例如:
(1)、创建NSDictionary对象
//使用过个value、key的形式创建NSDictionary对象
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:89],@"Objective-C",[NSNumber numberWithInt:69],@"Ruby",[NSNumber numberWithInt:75],@"Python",[NSNumber numberWithInt:109],@"Perl", nil];
(2)、获取一个路径
//获取路径
NSString *homePath = NSHomeDirectory();
NSString *path = [homePath stringByAppendingPathComponent:@"test.arc”];
(3)、归档
//对dict进行归档
[NSKeyedArchiver archiveRootObject:dict toFile:path];
(4)、解档
//解档
NSDictionary* dict1 = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
//下面代码只是获取NSDictionary中的key-value数据
NSLog(@"Objective-C对应的value:%@",[dict1 valueForKey:@"Objective-C"]);//Objective-C对应的value:89
NSLog(@"Ruby对应的value:%@",[dict1 valueForKey:@"Ruby"]);//Ruby对应的value:69
NSLog(@"Python对应的value:%@",[dict1 valueForKey:@"Python"]);//Python对应的value:75
NSLog(@"Perl对应的value:%@",[dict1 valueForKey:@"Perl"]);//Perl对应的value:109
如果尝试使用NSKeyedArchiver将一个自定义的类对象归档到指定文件中,运行程序将会提示如下错误:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[FKApple encodeWithCoder:]: unrecognized selector sent to instance 0x7faf62e46520'
*** First throw call stack:
从信息中可以看出,当程序使用NSKeyedArchiver归档一个自定义的FKApple对象时,系统会自动调用FKApple对象的encodeWithCoder:进行归档;当程序恢复一个自定义的实例时,系统会自动调用该对象的decodeWithCoder:方法进行恢复。所以,如果程序需要归档,恢复任意自定义的实例,那么该类应该实现NSCoding协议,实现该协议就必须实现该协议中定义的如下两个方法:
- initWithCoder::该方法负责恢复该对象。
- encodeWithCoder::该方法负责归档该对象。
例如:FKApple.h的实例部分
#import <Foundation/Foundation.h>
@interface FKApple : NSObject<NSCoding >
@property (nonatomic ,copy)NSString* color;
@property (nonatomic ,assign)double weight;
@property (nonatomic ,assign)int size;
- (id)initWithColor:(NSString *)color weight:(double)weight size:(int)size;
@end
FKApple.m的实现部分
#import "FKApple.h"
@implementation FKApple
- (id)initWithColor:(NSString *)color weight:(double)weight size:(int)size{
if (self = [super init]) {
self.color = color;
self.weight = weight;
self.size = size;
}
return self;
}
//归档
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:self.color forKey:@"color"];
[aCoder encodeDouble:self.weight forKey:@"weight"];
[aCoder encodeInt:self.size forKey:@"size"];
}
//解档
- (id)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {
//使用NSCoder依次恢复color、weight、size这3个key
//所对应的value,并将恢复的value赋给当前对象的3个实例变量
self.color = [aDecoder decodeObjectForKey:@"color"];
self.weight = [aDecoder decodeDoubleForKey:@"weight"];
self.size = [aDecoder decodeIntForKey:@"size"];
}
return self;
}
@end
在mian函数中的实现部分
//获取documents路径
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documents = [paths objectAtIndex:0];
NSString* path = [documents stringByAppendingPathComponent:@"apple.archiv"];
FKApple* apple = [[FKApple alloc]initWithColor:@"红色" weight:3.4 size:20];
//归档
[NSKeyedArchiver archiveRootObject:apple toFile:path];
//解档
FKApple* apple2 = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
//获取对象的属性
NSLog(@"苹果的颜色为:%@",apple2.color);//苹果的颜色为:红色
NSLog(@"苹果的重量为:%g",apple2.weight);//苹果的重量为:3.4
NSLog(@"苹果的规格为:%d",apple2.size);//苹果的规格为:20
如果程序需要一次性将多个对象归档到单个档案文件中,可按如下步骤进行:
例如:
//直接使用value、key的形式创建NSDictionary对象
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:89],@"Objective-C",[NSNumber numberWithInt:69],@"Ruby",[NSNumber numberWithInt:75],@"Python",[NSNumber numberWithInt:109],@"Perl", nil];
//创建一个NSSet对象
NSSet* set = [NSSet setWithObjects:@"疯狂iOS讲义",@"疯狂Android讲义",@"疯狂Ajax讲义", nil];
//创建一个FKApple对象
FKApple* apple = [[FKApple alloc]initWithColor:@"红色" weight:3.4 size:20];
//创建一个NSMutableData对象,用于保存归档数据
NSMutableData* data = [NSMutableData data];
//以NSMutableData为参数,创建NSKeyedArchiver对象
NSKeyedArchiver* arch = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
[arch encodeObject:dict forKey:@"myDict"];
[arch encodeObject:set forKey:@"set"];
[arch encodeObject:apple forKey:@"myApple"];
//结束归档
[arch finishEncoding];
//将程序NSData缓存区保存的数据写入文件
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documents = [paths objectAtIndex:0];
NSString* path = [documents stringByAppendingPathComponent:@"apple.archiv"];
NSLog(@"path = %@",path);
if ([data writeToFile:path atomically:YES] == NO) {
NSLog(@"归档失败");
}
NSData* data2 = [NSData dataWithContentsOfFile:path];
//以data2对象作为参数,创建NSKeyedUnichiver对象
NSKeyedUnarchiver* unarch = [[NSKeyedUnarchiver alloc]initForReadingWithData:data2];
//重复调用decodeObjectForKey:方法恢复所有需要恢复的对象
NSDictionary* dict2 = [unarch decodeObjectForKey:@"myDict"];
NSSet* set2 = [unarch decodeObjectForKey:@"set"];
FKApple* apple2 = [unarch decodeObjectForKey:@"myApple”];
//结束恢复
[unarch finishDecoding];
NSLog(@"dict2 = %@",dict2);
NSLog(@"set2 = %@",set2);
NSLog(@"apple2 = %@",apple2);
归档会将整个对象转换为字节数据——包括该对象的所有势力变量,如果该实例变量指向另一个Objecyive-C对象,归档时也会归档该实例变量所指向的Objective-C对象。这表明:当程序归档一个对象时,系统会把对象关联的所有数据都转为字节数据;如果程序从这些字节数据中恢复该对象,恢复出来的对象与原对象将完全相同,但没有任何共用的部分,这就是实现了深复制。