Objective-C Copy语法
来源:互联网 发布:淘宝天猫超市有客服吗 编辑:程序博客网 时间:2024/06/04 18:59
在OC语法中,提供了Copy语法(Copy + MutableCopy)用于对象的拷贝。其中很容易混淆的是浅拷贝和深拷贝。
所谓浅拷贝,即是地址拷贝,并不产生新的对象,而是对原对象的引用计数值加1即调用所谓的retain。而深拷贝,即是对象拷贝,产生新的对象副本,计数器为1,调用copy或mutableCopy。
何时用copy, 何时用 mutableCopy?
1、不可变对象→可变对象的转换:
NSArray *array1 = [NSArray arrayWithObjects:@"a",@"b",@"c",nil];NSMutableArray *str2 = [array1 mutableCopy];
2、可变对象→不可变对象的转换:
NSMutableArray *array2 = [NSMutableArray arrayWithObjects:@"aa",@"bb",@"cc",@"dd",nil];NSArray *array1=[array2 copy];
3、可变对象→可变对象的转换(不同指针变量指向不同的内存地址):
NSMutableArray *array1= [NSMutableArray arrayWithObjects:@"a",@"b", nil];NSMutableArray *str2=[array1 mutableCopy];
通过上边的两个例子,我们可以很方便的将一个对象在可变和不可变之间转换,并且这里不用考虑内存使用原则(即引用计数的问题)。这就是深拷贝的魅力所在。
4、同类型对象之间的导向保持(不同指针变量指向同一块内存地址):
NSMutableString *str1=[NSMutableString stringWithString:@"hello world"];NSMutableString *str2=[str1 retain];[str1 release];
NSArray *array1= [NSArray arrayWithObjects:@"a",@"b",@"c",nil];NSArray *str2=[array1 Copy];[array1 release];
通俗的讲,就是甲在执行交通导航任务,但接到上级新的命令要执行新的任务,那么在甲执行新任务之前,需要有人替代甲继续执行交通导航任务。这时候就要用到浅拷贝了。
则简化为:
问:什么时候用到深浅拷贝?
答:深拷贝是在要将一个对象从可变(不可变)转为不可变(可变)或者将一个对象内容克隆一份时用到;浅拷贝是在要复制一个对象的指针时用到。
下面通过一个例子来分析一下这个比较容易乱的Copy:
1. 对于NSString/NSMutableString; NSArray/NSMutableArray...这些OC提供的类对象:
以NSString/NSMutableString为例:
对于copy,返回的一定是不可变类型;而mutableCopy,返回的一定是可变类型。
①对于 mutableCopy,一定是深拷贝。
//对于 mutableCopy,都是深拷贝:对象的拷贝,产生新的对象void strMutableCopy(){ NSString *str=[[NSString alloc]initWithFormat:@"abcd"]; //产生了一个新的对象 计数器为1 原对象的计数器不变 NSMutableString *str2=[str mutableCopy]; //输出二者的地址,二者的地址是不同的 NSLog(@"str --> %p",str); NSLog(@"str2 --> %p",str2);}
②对于 copy:
如果是 NSString ---> NSString;则是浅拷贝;如果是 NSMutableString --->NSString;则是深拷贝。
如果是 NSString 、NSMutableString ---> NSMutableString;则是深拷贝。
Note :只有一种情况下是发生浅拷贝:不可变对象复制到不可变对象。
//浅拷贝:指针拷贝 不会产生新的对象,原对象计数器加1void strCopy(){ NSString *str=[[NSString alloc]initWithFormat:@"abcd"]; //因为NSString对象本身就不可变,所以并没产生新的对象,而是返回对象本身,会做一次retain操作,所以原对象也会retain NSString *str2=[str copy]; //输出二者的地址,二者的地址是相同的 NSLog(@"str --> %p",str); NSLog(@"str2 --> %p",str2);}
除了以上这种情形外,其他都是深拷贝。
2. 对于自定义对象的Copy:该类必须实现NSCopying协议,重写 copyWithZone方法。
同理,对于自定义对象的mutableCopy:必须实现 NSMutableCopying协议,重写 mutableCopyWithZone方法。
在NSCopying协议中,其实只有一个协议方法, 如下:
@protocol NSCopying- (id)copyWithZone:(NSZone *)zone;@end
在NSMutableCopying协议:
@protocol NSMutableCopying- (id)mutableCopyWithZone:(NSZone *)zone;@end
下面给出一个例子://// Person.h// test_1//// Created by lin on 14-8-26.// Copyright (c) 2014年 linshaolie. All rights reserved.//#import <Foundation/Foundation.h>@interface Person : NSObject<NSCopying>@property(nonatomic,copy) NSString *name;@property(nonatomic,assign) int age;-(id)initWithName:(NSString*)name andAge:(int)age;@end
//// Person.m// test_1//// Created by lin on 14-8-26.// Copyright (c) 2014年 linshaolie. All rights reserved.//#import "Person.h"@implementation Person-(instancetype)initWithName:(NSString*)name andAge:(int)age{ if ( self = [super init] ) { self.age = age; self.name = name; } return self;}-(id)copyWithZone:(NSZone *)zone{ Person* person = [[[self class] allocWithZone:zone] initwithName:self.name andAge:self.age]; return person;}@end
testing...//// main.m// test_1//// Created by lin on 14-8-26.// Copyright (c) 2014年 linshaolie. All rights reserved.//#import <Foundation/Foundation.h>#import "Person.h"#import "Student.h"int main(int argc, const char * argv[]){ @autoreleasepool { Person *per1 = [[Person alloc] initWithName:@"张三" andAge:12]; Person *per2 = [p1 copy]; //输出两个 Person 对象的地址,二者是不同的 NSLog(@"per1 --> %p",per1); NSLog(@"per2 --> %p",per2); } return 0;}
问:如果加入对于某些自定义对象是不可变的,怎么办呢?
答:只需要直接返回self就行了,如下:
-(id)copyWithZone:(NSZone *)zone{ return self;}
这样,输出的两个对象的地址就是相同的了。下面了解一下关于如果某一个自定义类继承了 这个Person类的情况。
如果某一个子类继承了实现了NSCopying协议的基类,那么该子类也是会自动继承这个协议的方法。但是需要自己重新实现。
例如:有一个Student子类继承了这个Person类:
//// Student.h// test_1//// Created by lin on 14-8-26.// Copyright (c) 2014年 linshaolie. All rights reserved.//#import <Foundation/Foundation.h>#import "Person.h"@interface Student : Person@property(nonatomic,copy)NSString *school;-(id)initWithName:(NSString *)name andAge:(int)age andSchool:(NSString*)school;@end
//// Student.m// test_1//// Created by lin on 14-8-26.// Copyright (c) 2014年 linshaolie. All rights reserved.//#import "Student.h"#import "Person.h"@implementation Student-(id)initWithName:(NSString *)name andAge:age andSchool:(NSString*)school{ self = [super initWithName:name andAge:name]; if ( self != nil ) { self.school = school; } return self;}-(id)copyWithZone:(NSZone *)zone{ Student *student = [super copyWithZone:zone]; student.school = self.school; return student;}@end
testing...//// main.m// test_1//// Created by lin on 14-8-26.// Copyright (c) 2014年 linshaolie. All rights reserved.//#import <Foundation/Foundation.h>#import "Person.h"#import "Student.h"int main(int argc, const char * argv[]){ @autoreleasepool { Student *student1 = [[Student alloc] initWithName:@"小明" andAge:20]; Student *student2 = [student1 copy]; //打印不同地址 NSLog(@"student1 --> %p", student1); NSLog(@"student2 --> %p", student2); } return 0;}
注意其中copyWithZone方法的实现。
最后,记录下另外一种实现深复制的方法:使用Foundation的归档技术。下面是代码:
NSArray *dataArray1 = @[@"aaa", @"bbb", @"ccc"]; NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dataArray1]; NSMutableArray *dataArray2 = [NSKeyedUnarchiver unarchiveObjectWithData:data]; // 上述即实现了将dataArray1深复制给dataArray2,另外一种简便写法是: NSLog(@"dataArray1 --> %p ", dataArray1); NSLog(@"dataArray2 --> %p ", dataArray2);
- Objective-C Copy语法
- 【Objective-C】Copy语法
- Objective-C 浅析Copy语法
- Objective-C之语法copy、mutablecopy以及自定义复制功能
- Objective-C Copy语法(一)对于Objective-C 提供的类对象NSString/NSMutableString; NSArray/NSMutableArray...
- Objective-C Copy语法(二)对于我们自定义对象Copy以及[self class]相关的错误
- 全面了解Objective-C:Copy
- Objective-C 语法规范
- Objective-c语法速成
- objective c 语法记录
- Objective-C 基础语法
- Objective-c基本语法
- Objective-C 语法
- Objective-C 语法
- Objective C基本语法
- Objective-C语法入门
- Objective-C语法总结
- Objective-C 基础语法
- ZOJ 3671 Japanese Mahjong III
- VC调用.dll文件
- poj 2528 Mayor's posters 线段树
- 关于thinkphp的几个问题:css路径问题,关联模型,
- 性能测试知多少---并发用户
- Objective-C Copy语法
- vs2010与matlab2009a混合编程
- 十二平均律
- headfirst servlet&jsp笔记
- 【机房收费系统——组合查询】
- poj1207~递归和打表
- 工作BUG
- Perl函数pack/unpack解释
- 设计模式:委托模式Delegation Pattern在MVC中的应用