以下内容转自被人博客
- copy设计的目的:改变副本的时候,不会影响到原来的对象
- 1、一个对象使用copy或者mutableCopy方法可以创建对象的副本
- 2、copy需要先实现NSCopying协议,创建的是不可改变副本(NSString、NSArray、NSDictionary)
- mutableCopy 需要先实现NSMutableCopying协议,创建的是可变副本(如NSMutableString、NSMutableArray、NSMutableDictionary)
- 3、深复制:内容拷贝,源对象和副本指向的是同一个对象。源对象引用计数器不变,副本计数器设置为1
- 浅复制:指针复制,源对象和副本对象指向的二十同一个对象,对象的引用对象加1,其实相当于做了一次retain操作
- 只有不可变对象创建不可变副本(copy)才是浅复制,其它都是深复制
- 4、NSString、NSArray、NSDictionary三种OC对象默认都已经实现了cooppying和NSMutableCopying协议
- 5、自定义类添加复制功能:
- 如果想自定义copy,那么必须遵守NSCopying,并实现copyWithZone:方法
- 如果想自定义mutableCopy,那么就必须遵守NSMutableCopying,并实现mutableCopyZone:方法
- 例如copy:
- 建议用self class 代替类名
- - (id)copyWithZone:(NSZone *)zone{
- id copy = [[[self class] allocWithZone:zone] init];
- //这儿开始做一些属性的初始化
- return copy;
- }
- 测试demo代码如下:
- 在这个demo中主要演示copy、mutableCopy,解说深拷贝、浅拷贝
- 以及自定义copy、mutableCopy的方法
- Student.h文件
- #import <Foundation/Foundation.h>
- @interface Student : NSObject<NSCopying>
- //copy代表set方法会release旧对象,copy新对象
- //修改外面的变量,并不会影响到内部的成员变量
- //建议:NSString一般用copy策略,其它对象一般用retain
- //retain 和外边是同一个对象,外边该了,里面这个name属性也会改
- @property (nonatomic, retain) NSString *name;
- + (id)studentWithName:(NSString *)name;
- @end
- Student.m文件:
- #import "Student.h"
- @implementation Student
- /**
- //@property (copy) :的意思如同下面这段setName方法
- - (void)setName:(NSString *)name{
- if(_name!=name){
- [_name release];
- _name = [name copy];
- }
- }
- **/
- + (id)studentWithName:(NSString *)name{
- //最好写slef class
- Student *stu = [[[[self class] alloc] init] autorelease];
- stu.name = name;
- return stu;
- }
- #pragma mark coping协议的方法
- //这里创建的副本对象不要求释放
- - (id)copyWithZone:(NSZone *)zone{
- Student *copy = [[[self class] allocWithZone:zone]init];
- copy.name = self.name;
- return copy;
- }
- //description 内部不能打印self不然会有死循环
- - (NSString *)description{
- return [NSString stringWithFormat:@"name=%@",_name];
- }
- - (void) dealloc{
- NSLog(@"student %@ is destoryed", self);
- [_name release];
- [super dealloc];
- }
- @end
- GoodStudent.h文件:
- #import "Student.h"
- @interface GoodStudent : Student
- @property (nonatomic, assign) int age;
- + (id) goodStudentWithAge:(int) age name:(NSString *)name;
- @end
- GoodStudent.m文件:
- #import "GoodStudent.h"
- @implementation GoodStudent
- + (id)goodStudentWithAge:(int)age name:(NSString *)name{
- GoodStudent *good = [GoodStudent studentWithName:name];
- good.age = age;
- return good ;
- }
- #pragma mark 重写父类的方法
- - (id)copyWithZone:(NSZone *)zone{
- //一定要调用父类的这个方法,因为父类帮我们copy了名字
- GoodStudent *copy = [super copyWithZone:zone];
- copy.age = self.age;
- return copy;
- }
- - (NSString *)description{
- return [NSString stringWithFormat:@"[name=%@, age=%i]",self.name, _age];
- }
- @end
- main测试方法:
- #import <Foundation/Foundation.h>
- #import "Student.h"
- #import "GoodStudent.h"
- void stringMutableCopy(){
- NSString *string = [[NSString alloc] initWithFormat:@"age is %i",10];
- //产生一个新的对象,计数器为1,源对象的计数器不改变
- NSMutableString *str = [string mutableCopy];
-
- NSLog(@"string: %zi",[string retainCount]); //1
- NSLog(@"str :%zi",[str retainCount]); //1
- //str和string不是相同对象
- NSLog(@"%i",str ==string);//0
-
- [str release];
- [string release];
-
- }
- /**
- 只有这一种情况是浅拷贝:指针拷贝,不会产生新的对象
- **/
- void stringCopy(){
- NSString *string = [[NSString alloc] initWithFormat:@"age is %i",10];
- //copy是不可变副本,由于源对象本身就不可变,所以为了性能着想,copy直接返回源对象本身
- // 源对象计数器+1
- NSString *str = [string copy];
- NSLog(@"%zi",[string retainCount]); //2
- NSLog(@"%zi",[str retainCount]); //2
- //相同对象
- NSLog(@"%i",str == string); //1
-
- [str release];
- [string release];
- }
- /**
- 只有一种情况浅拷贝:string-string
- **/
- // 定义个字符串
- NSString *s1 = @"itheima";
-
- // 浅复制
- NSString *s2 = [s1 copy];
- //深拷贝 【这地方本人是有疑惑的,怀疑原博客主人写错了】
- void mutableStringCopy(){
- NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i",10];
- NSString *str = [string copy];
-
- NSLog(@"%i",str == string); //0
- }
- //深拷贝
- void mutableStringMutableCopy(){
- NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i",10];
- NSMutableString *str = [string mutableCopy];
- NSLog(@"%i",str == string ); //0
-
- [str appendString:@"abc"];
- NSLog(@"%@", str); //10abc
-
- }
- //stendent属性的copy
- void studentNameCopy(){
- Student *stu = [[[Student alloc]init] autorelease];
- NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i", 10];
-
- stu.name = string;
-
- [string appendString:@"abcd"];
-
- NSLog(@"stu.name=%@",stu.name);
- NSLog(@"string=%@",string);
- }
- //stendent对象的copy
- void studentCopy(){
- Student *stu1 = [Student studentWithName:@"stu1"];
- Student *stu2 = [stu1 copy];
-
- NSLog(@"stu1:%@",stu1.name);
- NSLog(@"stu2:%@",stu2.name);
-
- stu2.name = @"stu2";
-
- NSLog(@"stu1:%@",stu1.name);
- NSLog(@"stu2:%@",stu2.name);
- NSLog(@"%i",stu1 == stu2);
-
- [stu2 release];
- }
- //GoodStudent子类的copy
- void goodStudent(){
- GoodStudent *goodStu1= [GoodStudent goodStudentWithAge:20 name:@"goodStu1"];
- NSLog(@"goodStu1:%@",goodStu1);
-
- GoodStudent *goodStu2 = [goodStu1 copy];
- NSLog(@"goodStu2:%@",goodStu2);
- }
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- NSLog(@"----stringMutableCopy----");
- stringMutableCopy();
- NSLog(@"----stringcopy----");
- stringCopy();
- NSLog(@"----mutableStringCopy----");
- mutableStringCopy();
- NSLog(@"----mutableStringMutableCopy----");
- mutableStringMutableCopy();
- NSLog(@"----studentNameCopy----");
- studentNameCopy();
- NSLog(@"----studentCopy----");
- studentCopy();
- NSLog(@"----goodStudent----");
- goodStudent();
- }
- return 0;
- }
复制代码 |