Objective-C之语法copy、mutablecopy以及自定义复制功能

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
 **/
//深拷贝
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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值