ios 深度复制 copy & mutablecopy
2015-10-08 21:00
471 查看
首先讲一下
copy 遵守NSCopying,并且实现 copyWithZone: 方法; 可以copy一个对象(OC已实现类,返回的是不可变对象,即使是NSMutableString和NSMutableArray,返回值 是NSString和NSArray这种)。 mutableCopy 遵守NSMutableCopying,并且实现 mutableCopyWithZone: 方法 可以mutableCopy一个对象 (NSMutableString返回是 NSMutableString)。 注意的一点是,不管是mutableCopy 还是 copy ,如果是NSArray里面的元素是对象的引用,那么复制出来的仍旧是引用。(简单的想,有一个数组A,里面的值是地址0x123,那么copy出来的数组,对应的值应该还是0x123.而0x123对应着一个对象的地址) 那怎么做深度复制,把地址0x123对应的内存也复制过去? 回想下,NSUserDefaults存放的数组,数组里面的对象的值,和 下次加载的时候对象的值是一样的,但是内存的地址是完全不一样的。 那么,这样可以做到,完全复制!
NSArray* newArr = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject: array]]; 其实就是一个序列化的过程。 接下来,如果copy 或者 序列化的容器类或者对象类里面,含有自定义的类的时候,应该怎么办? 1,copy 的问题。 CustomClass 要实现 NSCopying 协议。
- (id)copyWithZone:(NSZone *)zone;
在上面的方法中,增加初始化和复制的过程。
相当于 A = [B copy];调用的过程中,B会调用copyWithZone的函数,然后用自身的数据去分配和初始化 一个新的类,然后把这个类作为返回值Bnew, A = Bnew;
2,序列化的问题。
CustomClass 要实现 NSCoding 协议。
在- (void)encodeWithCoder:(NSCoder *)coder 函数中,把属性值一个个调用[coder encodeObject:tempValue forKey:propertyName];
在- (instancetype)initWithCoder:(NSCoder *)aDecoder 函数中,把属性值一个个[self setValue:[aDecoder decodeObjectForKey:propertyName] forKey:propertyName];
这个两步都是一个繁琐的过程。
然后就想一劳永逸下:
@interface LYCoding : NSObject <NSCoding, NSCopying>
@end
@implementation LYCoding
- (id)copyWithZone:(NSZone *)zone
{
id ret = [[[self class] allocWithZone:zone] init];
unsigned int propertyCount = 0;
objc_property_t * properties = class_copyPropertyList( [self class], &propertyCount );
for ( NSUInteger i = 0; i < propertyCount; i++ )
{
const char * name = property_getName(properties[i]);
NSString * propertyName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
NSObject<NSCopying> * tempValue = [self valueForKey:propertyName];
if (tempValue) {
id value = [tempValue copy];
[ret setValue:value forKey:propertyName];
}
}
return ret;
}
- (void)encodeWithCoder:(NSCoder *)coder
{
unsigned int propertyCount = 0;
objc_property_t * properties = class_copyPropertyList( [self class], &propertyCount );
for ( NSUInteger i = 0; i < propertyCount; i++ )
{
const char * name = property_getName(properties[i]);
NSString * propertyName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
NSObject * tempValue = [self valueForKey:propertyName];
// [tempValue conformsToProtocol:@protocol(NSCoding)];
[coder encodeObject:tempValue forKey:propertyName];
}
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init]) {
unsigned int propertyCount = 0;
objc_property_t * properties = class_copyPropertyList( [self class], &propertyCount );
for ( NSUInteger i = 0; i < propertyCount; i++ )
{
const char * name = property_getName(properties[i]);
NSString * propertyName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
[self setValue:[aDecoder decodeObjectForKey:propertyName] forKey:propertyName];
}
}
return self;
}
@end
这个是我自定义的基类,实现copy 和 coding的协议。新的类如果需要就直接继承这个类。
[tempValue conformsToProtocol:@protocol(NSCoding)];
这一行代码有什么用?
因为这个类还不完善,如果CustomA类中,有一个属性值是CustomB类。
那么需要在encode A类的时候,判断下每个值 的属性,是否实现了NSCoding,如果是,那么把它序列化成NSData.(NSData *personEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:item];)
因为在这个项目,还用不到这个东西,所以就没加上去。
相关文章推荐
- iOS8之后利用storyboard、xib动态获取行高
- ios图形上下文CGContext
- iOS:触摸事件和手势识别的介绍
- iOS视图控制对象生命周期及其作用
- ios中block中的探究
- 苹果IOS开发常用的第三方库总结
- IOS异常日志记录与展现功能
- iOS开发 大文件下载封装
- iOS的触摸与手势识别
- iOS9的 NSURLSession
- 为固定高度的网页元素添加 iOS Safari 滚动「惯性效果」的方法
- iOS开发Provisioning profile解析
- IOS读取图片(转载)
- iOS效果 :(1) CALayer 图层阴影,边框,圆角,圆型图片的阴影
- iOS NSString 字符串处理:截取字符串、匹配字符串、分隔字符串、拼接字符串、替换字符串
- nagios4.1.1 服务端及监控端部署(二)之pnp4nagios 配置出图
- iOS异步加载缓存图片
- iOS:对GCD中 同步、异步、并行、串行的见解
- ios开发,javascript直接调用oc代码
- xcode生成的IOS安装文件的位置