11、复制对象

1、复制对象的基本概念

·复制对象的基本概念
复制对象顾名思义,复制一个对象作为副本,它会开辟一块新的内存(堆内存)来存储副本对象,就像复制文件一样。即源对象和副本对象是两块不同的内存区域。

对象具备复制功能,必须实现 :

·<NSCopying>协议
·<NSMutableCopying>协议
·常用的可复制对象有:NSNumber、NSString、NSArray、NSDictionary、
NSMutableDictionary、NSMutableArray、NSMutableString

·复制对象的种类

·copy:产生对象的副本是不可变的
·mutableCopy:产生的对象副本是可变的

·创建一个数组(包含元素:one,two,three等),然后分别对它进行保留和拷贝操作,删除其中的一个元素,看看发生了什么?

//同块堆内存
NSMutableArray *array1 = [[NSMutableArrayalloc]initWithObjects:@"one",@"two",@"three",@"foure", nil];
NSMutableArray *array2 = [array1 retain];
[array2 removeLastObject];

NSLog(@"%@",array1);
NSLog(@"%ld",array1.retainCount);
//新的块堆内存
NSMutableArray *array1 = [[NSMutableArrayalloc]initWithObjects:@"one",@"two",@"three",@"foure", nil];
NSMutableArray *array2 = [array1 mutableCopy];
[array2 removeLastObject];
NSLog(@"%@",array1);

COPY和MUTABLECOPY的区别

·copy和mutableCopy的区别 ·前者返回一个不可变对象副本,后者返回一个可变对象副本

NSArray *array = [NSArray arrayWithObjects:@"aaa",@"bbb",@"ccc", nil]; 

//返回不可变数组
NSArray *arrayCopy = [array copy];
//返回可变数组
NSMutableArray *mutableCopy = [array mutableCopy]; 
[mutableCopy addObject:@"ddd"]; 
NSLog(@"arrayCopy: %@",arrayCopy); 
NSLog(@"mutableCopy: %@",mutableCopy);

2、浅拷贝和深拷贝基本概念和用法

深浅复制的基本概念
·浅复制只复制对象的本身,对象里的属性、包含的对象不做复制。
·深复制则即复制对象本身,对象的属性也会复制一份。
·Foundation框架中支持复制的类,默认是浅复制。
这里写图片描述

例如: 一个数组包含了许多个对象,复制一个数组的副本,那么两个数组中的元素是没复制的,指向的还是同一个对象。

        NSMutableArray *array = [NSMutableArray array];
        for (int i=0; i<3; i++) {
            NSObject *obj = [[NSObject alloc] init];
            [array addObject:obj];
            [obj release];
        }

        for (NSObject *obj in array) {
            NSLog(@"指针地址:%p, 引用计数:%ld",obj,obj.retainCount);
        }

        NSArray *array2 = [array copy];
        for (NSObject *obj in array2) {
            NSLog(@"指针地址:%p, 引用计数:%ld",obj,obj.retainCount);
        }        
        [array2 release];

3、对象的自定义拷贝

·对象拥有复制特性,须实现NSCopying、NSMutableCopying协议,实现该协议的copyWithZone:方法和mutableCopyWithZone:方法。

@interface Person : NSObject<NSCopying>

@property(nonatomic,copy)NSMutableString *name;
@property(nonatomic,retain)NSNumber *age;

@end
/********返回的是不可变对象**********/
- (id)copyWithZone:(NSZone *)zone {
    User *user = [[[self class] allocWithZone:zone] init];
    user.data = _data;
    return user;
} 
@interface Person : NSObject<NSMutableCopying>

@property(nonatomic,copy)NSMutableString *name;
@property(nonatomic,retain)NSNumber *age;

@end
/********返回的是可变对象**********/
- (id)mutableCopyWithZone:(NSZone *)zone {
UserMutable *user = [[[self class] allocWithZone:zone] init]; user.data = _data;
return user;
} 

深、浅复制的不同实现

·Objective-C对象的深、浅拷贝的区别就在于你对copyWithZone的不同实现

- (id)copyWithZone:(NSZone *)zone {
    /**浅复制的实现**/
    Person *p = [[[self class] allocWithZone:zone] init];
    p.name = _name;
    p.age = _age;
    return p;
}
- (id)copyWithZone:(NSZone *)zone {
    /**深复制的实现**/
    Person *p = [[[self class] allocWithZone:zone] init];
    p.name = [_name copy];
    p.age = [_age copy];
    return p;
}

4、深、浅拷贝和RETAIN之间的总结

copy、mutableCopy和retain之间的关系
·Foundation可复制的对象,当我们copy的是一个不可变的对象时,它的作用相当于retain(cocoa做的内存优化)
·当我们使用mutableCopy时,无论源对象是否可变,副本是可变的,并且实现了真正意义上的拷贝
·当我们copy的是一个可变对象时,副本对象是不可变的,同样实现了真正意义上的拷贝

我们创建一个汽车类,汽车拥有一个Engine对象,一个车重和一个名字,实现下他的深复制和浅复制。

//Engine.h
#import <Foundation/Foundation.h>

@interface Engine : NSObject<NSCopying>

@end
//Engine.m
#import "Engine.h"

@implementation Engine

- (id)copyWithZone:(NSZone *)zone {
    Engine *engine = [[[self class] allocWithZone:zone] init];
    return engine;
}

- (void)dealloc {
    NSLog(@"engine dealloc");
    [super dealloc];
}

@end
//Car.h
#import <Foundation/Foundation.h>

@class Engine;
@interface Car : NSObject<NSCopying>

@property(nonatomic,retain)Engine *engine;
@property(nonatomic,retain)NSNumber *weight;
@property(nonatomic,copy)NSString *name;

@end
//Car.m
#import "Car.h"
#import "Engine.h"

@implementation Car

- (id)copyWithZone:(NSZone *)zone {
    /***浅拷贝**/
    Car *car = [[[self class] allocWithZone:zone] init];
    car.engine = _engine;
    car.weight = _weight;
    car.name = _name;

    /***深拷贝**/
//    Car *car = [[[self class] allocWithZone:zone] init];
//    Engine *engine = [_engine copy];
//    NSNumber *weight = [_weight copy];
//    NSString *name = [_name copy];
//    
//    car.engine = engine;
//    car.weight = weight;
//    car.name = name;
//    
//    [engine release];
//    [weight release];
//    [name release];

    return car;
}

- (void)dealloc {
    NSLog(@"car dealloc");
    [_weight release];
    [_name release];
    [_engine release];
    [super dealloc];
}

@end
//main.m
#import <Foundation/Foundation.h>
#import "Car.h"
#import "Engine.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        Car *car = [[Car alloc] init];
        Engine *engine = [[Engine alloc] init];
        car.engine = engine;
        [engine release];
        car.name = @"奥迪";
        car.weight = @1000;

        Car *car2 = [car copy];

        NSLog(@"car:%@, car2:%@",car,car2);

        [car release];
        [car2 release];

    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值