复制对象、对象归档和单例

来源:互联网 发布:甄嬛传 三观不正 知乎 编辑:程序博客网 时间:2024/05/29 19:49

1、复制对象的基本概念 

·复制对象的基本概念 复制对象顾名思义,复制一个对象作为副本,它会开辟一块新的内存(堆内存)
 来存储副本对象,就像复制文件一样。即源对象和副本对象是两块不同的内存区
域。
·对象具备复制功能,必须实现 ·<NSCopying>协议
·<NSMutableCopying>协议 
·常用的可复制对象有:NSNumber、NSString、NSArray、NSDictionary、NSMutableDictionary、NSMutableArray、NSMutableString 
·复制对象的种类
·copy:产生对象的副本是不可变的
·mutableCopy:产生的对象副本是可变的


·创建一个数组(包含元素:one,two,three等),然后分别对它进行保留、 和拷贝操作,删除其中的一个元素,看看发生了什么?

NSMutableArray *mutableArray =[NSMutableArray arrayWithObjects:@"one",@"two",@"three", @"four", nil];NSMutableArray *retainArray =[mutableArray retain];[mutableArray removeLastObject];for (NSString *string in retainArray) {NSLog(@"string : %@", string); } // 同⼀一块堆内存

NSMutableArray *mutableArray =[NSMutableArray arrayWithObjects:@"one", @"two",@"three", @"four", nil];NSMutableArray *copyArray =[mutableArray mutableCopy];[copyArray removeLastObject];for (NSString *string in mutableArray) {NSLog(@"string : %@", string); } // 新的⼀一块堆内存


COPY和MUTABLECOPY的区别

·copy和mutableCopy的区别 ·前者返回一个不可变对象副本,后者返回一个可变对象副本
·示例:

NSArray *array = [NSArray arrayWithObjects:@"aaa",@"bbb",@"ccc", nil]; //返回不可变数组NSArray *arrayCopy = [array copy];//返回可变数组NSMutableArray *mutableCopy = [array mutableCopy]; [mutableCopy addObject:@"ddd"]; NSLog(@"arrayCopy: %@",arrayCopy); NSLog(@"mutableCopy: %@",mutableCopy);

2、浅拷贝和深拷贝基本概念和用法

·深浅复制的基本概念 ·浅复制只复制对象的本身,对象里的属性、包含的对象不做复制。
·深复制则即复制对象本身,对象的属性也会复制一份。 

·Foundation框架中支持复制的类,默认是浅复制。


·例如: 一个数组包含了许多个对象,复制一个数组的副本,那么两个数组中的 元素是没复制的,指向的还是同一个对象。

NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:3];for (int i=0; i<3; i++) {     NSObject *obj = [[NSObject alloc] init];     [array addObject:obj];     [obj release];}for (NSObject *o in array) {NSLog(@"复制之前: retainCount: %lu",[o retainCount]);}NSArray *newArray = [array copy];for (NSObject *o in newArray) {NSLog(@"复制之后: retainCount: %lu",[o retainCount]);}

3、对象的自定义拷贝

·对象拥有复制特性,须实现NSCopying、NSMutableCopying协议,实现该 协议的copyWithZone:方法和mutableCopyWithZone:方法。

- (id)copyWithZone:(NSZone *)zone {    User *user = [[[self class] allocWithZone:zone] init];    user.data = _data;    return user;} // 返回的是不可变对象

- (id)mutableCopyWithZone:(NSZone *)zone {UserMutable *user = [[[self class] allocWithZone:zone] init]; user.data = _data;return user;} // 返回的是可变对象

深、浅复制的不同实现
·Objective-C对象的深、浅拷贝的区别就在于你对copyWithZone的不同实现

- (id)copyWithZone:(NSZone *)zone {// /**浅复制的实现**///    Person *p = [[[self class] allocWithZone:zone] init];//    p.name = _name;//    p.age = _age;// return p;/**深复制的实现**/Person *p = [[[self class] allocWithZone:zone] init]; p.name = [_name copy];p.age = [_age copy];return p;}

4、深、浅拷贝和RETAIN之间的总结

·copy、mutableCopy和retain之间的关系·Foundation可复制的对象,当我们copy的是一个不可变的对象时,它的作用相当于retain(cocoa做的内存优化)
·当我们使用mutableCopy时,无论源对象是否可变,副本是可变的,并且实现了真正意义上的拷贝
·当我们copy的是一个可变对象时,副本对象是不可变的,同样实现了真正意义上的拷贝 


复制对象总结

·复制对象的概念,浅复制、深复制的区别。 
·自定义对象如何支持复制,实现NSCopying协议。 
·自定义对象如何实现深复制和浅复制。 
·Foundation框架中支持复制的对象需要注意的地方。


5、对象归档的基本概念和用法

·概念: 对象归档是指将对象写入文件保存在硬盘上,当再次重新打开程序时, 可以还原这些对象。你也可以称它为对象序列化、对象持久化
·数据持久性的方式 ·NSKeyedArchiver——对象归档
·NSUserDefaults
·属性列表化( NSArray、NSDictionary保存文件) ·SQlite数据库、Core Data数据库
·归档的形式 
·对Foundation库中对象进行归档
·自定义对象进行归档(需要实现归档协议,NSCoding) 
·归档后的文件是加密的, 属性列表是明文的。


·我们就以数组为例,实现一个数组的序列化和反序列化

//   归档(序列化)NSString *homeDirectory = NSHomeDirectory();NSArray *array = @[@123, @456, @"999", @"000"];NSString *directoryA = [homeDirectory stringByAppendingPathComponent:@"array.archive"];if ([NSKeyedArchiver archiveRootObject:array toFile:directoryA]) {    NSLog(@"archiver success");}// 解归档(反序列化)NSArray *unArray = [NSKeyedUnarchiver unarchiveObjectWithFile:directoryA]; NSLog(@"new Array : %@", newArray);

自定义内容归档
·归档 
·使用NSData实例作为归档的存储数据
·添加归档的内容(设置key与value) 
·完成归档
·将归档数据存入磁盘中

·解归档 
·从磁盘读取文件,生成NSData实例
·根据Data实例创建和初始化解归档实例 
·解归档,根据key访问value的值

·自定义一个基本数据类型和一个objective-c对象类型,进行对象的归档和解归 档

// 归档 (序列化)NSString *homePath = NSHomeDirectory();NSString *filePath = [homePath stringByAppendingPathComponent:@"customContent.archive"]; NSMutableData *data = [NSMutableData data]; NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];[archiver encodeFloat:50 forKey:@"weight"];[archiver encodeObject:@"jack" forKey:@"name"]; [archiver finishEncoding];[archiver release];[data writeToFile:filePath atomically:YES];// 解归档(反序列化)NSData *content = [NSData dataWithContentsOfFile:filePath];NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:content];float weight = [unarchiver decodeFloatForKey:@"weight"];NSString *name = [unarchiver decodeObjectForKey:@"name"];

自定义对象的归档基本概念

·自定义的对象要支持归档,需要实现NSCoding协议。 
·NSCoding协议有两个方法,encodeWithCoder 方法对对象的属性数据做编码处理。initWithCoder 解码归档数据来初始化对象 
·实现NSCoding协议后,就能通过NSKeyedArchiver归档。 
·示例:

// 解码方法- (id)initWithCoder:(NSCoder *)aDecoder {    self = [super init];    if (self != nil) {        _name = [[aDecoder decodeObjectForKey:@"name"] copy];        _age = [aDecoder decodeIntForKey:@"age"];        _apples = [[aDecoder decodeObjectForKey:@"apples"] retain];    }    return self;}

// 编码方法- (void)encodeWithCoder:(NSCoder *)aCoder {    [aCoder encodeObject:_name forKey:@"name"];    [aCoder encodeObject:_apples forKey:@"apples"];    [aCoder encodeInt:_age forKey:@"age"];}

归档总结

·归档和解归档的两种方式 
·自定义对象如何归档,实现NSCoding协议。 
·归档后的文件是加密的。


6、单例设计模式

·基本概念 单例设计模式运用较为普遍、广泛且较为简单的设计模式之一,它的设计原理是:始终返回一个实例,即一个类始终只有一个实例。



创建单例的基本步骤

·创建单例设计模式的基本步骤 
·声明一个单件对象的静态实例,并初始化为nil。
·创建一个类的类工厂方法,生成一个该类的实例,当且仅当这个类的实例为nil时 
·覆盖allocWithZone:方法,确保用户(程序员)在直接分配和初始化对象时,不会产生另一个对象。
·实现NScopying协议,覆盖release、autorelease、retain、retainCount方法, 以此确保单例的状态。
·在多线程的环境中,注意使用@synchronized关键字,确保静态实例被正确的创建 和初始化。


单例的基本实现

·定义静态对象和工厂方法

//  定义⼀一个静态实例,并初始化为nil static File *shareFile = nil;+ (File *)shareFile{@synchronized (self) { // 线程保护 // 如果实例为nil,则创建该实例 if (shareFile == nil) {            shareFile = [[self alloc] init];        }}    return shareFile;}// 覆盖allocWithZone:方法+ (id)allocWithZone:(NSZone *)zone{    NSLog(@" nil %p", zone);    @synchronized (self) {        if (shareFile == nil) {            shareFile = [super allocWithZone:zone];            return shareFile;         }      }    return shareFile;}// 实现copy协议,覆盖与内存相关的方法- (id)copyWithZone:(NSZone *)zone{    return self;} // 实现copy协议,返回本身- (id)retain{    return self; } // 返回本身- (NSUInteger)retainCount{    return UINT_MAX;} // 返回⼀一个无符号整型范围最大值- (oneway void)release{} // 什么都不做- (id)autorelease{    return self;} // 返回对象本身




0 0
原创粉丝点击