Objective-C之深拷贝与浅拷贝

在iOS开发中, 我们往往会使用一些文字描述, 如论外界如何改变, 描述都不改变, 此时我们就会使用到copy或者mutableCopy


要是是使用copy/mutableCopy, 必须要遵守NSCoping/NSMutableCoping协议, 并且实现协议中的方法

copy/mutableCopy语法的本质是:产生新对象,当改变新对像时,不改变源对象

    1>调用copy返回的是不可变的,调用mutableCopy返回的时可变的

    2>不可变类型的调用的copy方法,是浅拷贝(指针拷贝,地址拷贝),新对象和源对象指向的是同一对象,源对象的计数器+1变成2

    3>其他情况下,都是产生新对象,源对象的计数器不变,新对象的计数器置为1


1.系统自带类的拷贝

#pragma mark - NSStringcopy(浅拷贝,指针拷贝,地址拷贝)

//不可变copy---->不可变,只是地址(指针)的拷贝,新对象和源对象指向同一对象,源对象的计数器+1变成2

NSString *string = [[NSString alloc] initWithFormat:@"age is %i", 10];
    
    NSLog(@"%zi", [string retainCount]);//
    
    NSString *str = [string copy];// 返回不变的,为了性能着想, 干脆返回源对像, 相当于retain
    
    NSLog(@"%zi", [str retainCount]);
    
    //产看是否产生新的对象
    BOOL isEqual = (str==string);
    NSLog(@"isEqual = %i", isEqual);
    
    NSLog(@"string = %p, str = %p", string, str);//通过打印内存地址诶查看, 内存地址相等
    
    [str release];
    [string release];


#pragma mark - NSStringMutabelCopy(深拷贝)对象拷贝

//深拷贝(对象拷贝),源对象计数器不变, 新计数器置1

NSString *string = [[NSString alloc] initWithFormat:@"age is %i", 10];
    NSLog(@"%zi", string.retainCount); //1
    
    NSMutableString *str = [string mutableCopy];
    NSLog(@"%zi", str.retainCount); //1

    [str appendString:@" abcd"];
    
    BOOL isEqual = (str==string);
    NSLog(@"isEqual = %i", isEqual);// 0
    
    NSLog(@"string = %@", string); //string = age is 10
    NSLog(@"str = %@", str); //str = age is 10 abcd

#pragma mark - NSMutableStringcopy(深拷贝)

NSMutableString *string = [[NSMutableString alloc] initWithFormat:@"age is %i", 10];
    NSLog(@"%zi", string.retainCount); //1
    
    NSString *str = [string copy];
    NSLog(@"%zi", str.retainCount); //1
    
    [string appendString:@" abcd"];
    
    NSLog(@"string = %@", string); //string = age is 10 abcd
    NSLog(@"str = %@", str); //str = age is 10

#pragma mark - NSMutableStringMutableCopy(深拷贝)

NSMutableString *string = [[NSMutableString alloc] initWithFormat:@"age is %i", 10];
    NSLog(@"%zi", string.retainCount);
    
    NSMutableString *str = [string mutableCopy];
    NSLog(@"%zi", str.retainCount);
    
    [string appendString:@" abcd"];
    [str appendString:@"lllllll"];

    NSLog(@"string = %@", string); //string = age is 10 abcd
    NSLog(@"str = %@", str); //str = age is 10lllllll

2.自定义对象的拷贝

1>




//Person类

//Person.h

#import <Foundation/Foundation.h>

@interface Person : NSObject <NSCopying, NSMutableCopying>

//copy代表set方法会release就对象,copy新对象
//修改外边的变量, 并不会影响到内部的成员变量
//建议:NSString一般用copy策略, 其他对象一般用retain
@property (nonatomic, copy, readwrite) NSString *name;

+ (instancetype)personWithName:(NSString *)name;

- (instancetype)initWithName:(NSString *)name;

@end


//Person.m
#import "Person.h"

@implementation Person

- (id)copyWithZone:(NSZone *)zone{
    
    Person *copy = [[[self class] allocWithZone:zone] init];
//拷贝属性
    copy.name = self.name;// 等价于copy.name = [self.name copy];
    /*
     按道理只需要这样copy.name = [self.name copy];就能实现深拷贝,
     copy.name = [self.name copy];
     
     a:如果是Foundation框架里的不可变对象,就是Array,NSString等创建的对象,直接用copy来拷贝相当于retain,也就是属性还是同一个;
     
     b:如果是用mutableCopy来拷贝,不管是可变还是不可变对象,属性神马的都直接拷贝了一份,即真正意义上得拷贝,它拷贝出来的对象统统都是可变的;
     
     c:如果是可变对象,我们用copy也能实现真正意义上的拷贝,但是拷贝出来的对象是不可变的。

     */

    return copy;
}

-(id)mutableCopyWithZone:(NSZone *)zone{
    
    Person *mutableCopy = [[[self class] allocWithZone:zone] init];
    mutableCopy.name = [self.name mutableCopy];

    return mutableCopy;
}

-(instancetype)initWithName:(NSString *)name{

    _name = name;
    return self;
}

+(instancetype)personWithName:(NSString *)name{

    Person *p = [[Person alloc] init];
    p.name = name;
    return p;
}


- (NSString *)description
{
    return [NSString stringWithFormat:@"%@:[name = %@]", [self class], self.name];
}


#pragma mark - person Copy

// copy 对象的地址不同, 但是属性的地址相同

NSString *str = [[NSString alloc] initWithFormat:@"zhaofei is %i", 10];
    Person *person = [Person personWithName:str];
    
    NSLog(@"person = %p", person);
    NSLog(@"person.name = %p", person.name);
    NSLog(@"%zi", person.retainCount);// 计数器为2
    NSLog(@"%zi", person.name.retainCount);// 计数器为1
    
//    NSLog(@"person.age = %p", person.age);
    
    Person *p = [person copy];
//    p.name = @"aksdlk";
    
    NSLog(@"p = %p", p);
    NSLog(@"p.name = %p", p.name);
    NSLog(@"%zi", p.retainCount);// 计数器为1
    NSLog(@"%zi", p.name.retainCount);// 计数器为4
    
    
    NSLog(@"%@", person);
    NSLog(@"%@", p);

#pragma mark - person mutableCopy

// 需要在mutableCopyZone方法里将属性用mutbaleCopy方式进行拷贝

//对象的地址不同, 但是属性的地址不同

<span style="white-space:pre">	</span>NSString *str = [[NSString alloc] initWithFormat:@"zhaofei is %i", 10];

        Person *person = [Person personWithName:str];
        NSLog(@"person = %p", person);
        NSLog(@"person.name = %p", person.name);
        NSLog(@"%zi", person.retainCount);// 计数器为1

        Person *p = [person mutableCopy];
        NSLog(@"p = %p", p);
        NSLog(@"p.name = %p", p.name);
        NSLog(@"%zi", p.retainCount);// 计数器为1


        str = @"kaslkdadkasd";//不会修改对象里面的属性值

        NSLog(@"%@", person);
        NSLog(@"%@", p);

3. 定义一个Student类, 继承Person类, 并且声明一些Person中没有的属性的时候, 如果要使用copy/mutableCopy, 就应该重写父类Person的- (instancetype)copyWithZone:(NSZone *zone)  和 - (instancetype)mutableCopyWithZone:(NSZone *)zone方法, 并且在方法要拷贝对象的属性









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值