【黑马程序员】copy与mutableCopy实例

---------- IOS培训java培训、期待与您交流! ----------

一个对象使用copy 与 mutableCopy可以创建一个对象的副本

copy--需要实现NSCopying协议,创建的是不可变副本(如NSString,NSArray,NSDictionary)

mutableCopy---需要实现NSMutableCopying协议,创建的是可变副本(如NSMutableString,NSMutableArray,NSMutableDictionary)

用一个专业术语来描述拷贝

深拷贝:内容拷贝,源对象和副本指向的不是两个对象。源对象引用计数器不变,副本计数器设置为1。

浅拷贝:指针拷贝,源对象和副本指向的是同一个对象。对象引用计数器加1,相当于做了一次retain操作。

只有不可变对象创建不可变副本的时候才是浅拷贝,其它任何时候都是深拷贝。---即,当对象不同的时候就一定是深拷贝。

#pragma mark 演示字符串的拷贝(浅拷贝)

// 只有一种情况是浅拷贝:不可变对象调用copy方法时


// 浅拷贝:指针拷贝,不会产生新的对象。源对象计数器+1

void stringCopy() {

    NSString *string = [[NSString alloc] initWithFormat:@"age is %i", 10];

    NSLog(@"%zi", [string retainCount]);

    

    // copy产生的是不可变副本,由于源对象本身就不可变,所以为了性能着想,copy会直接返回源对象本身

    // 源对象计数器会+1

    // 在浅拷贝情况下,copy其实就相当于retain

    NSString *str = [string copy];

    NSLog(@"%zi", [string retainCount]);

    

    // NSLog(@"%i", str == string);

    

    [str release];

    [string release];

}


 

#pragma mark mutableStringMutablecopy

void mutableStringMutableCopy(){

    

   NSMutableString*  str1= [NSMutableString stringWithFormat:@"hello world %i",2015];

    //[str1 appendFormat:@"hello world"];

    NSMutableString* str2=  [str1 mutableCopy];

   

    [str2 appendString:@" haha"];

    NSLog(@"str1%@",str1);

    NSLog(@"str2%@",str2);

    [str2 release];


}

得到

2015-03-04 11:52:23.001 CopyAndMutableCopy[884:40088] str1hello world 2015

2015-03-04 11:52:23.002 CopyAndMutableCopy[884:40088] str2hello world 2015 haha

Program ended with exit code: 0


可以看出可变字符串的mutablecopy得到的另一个可变字符串,两者之间只是内容间的拷贝。修改str2,并不会改变str1的值。


下面我们通过代码来阐述对象间的copy方法。-----------

首先我们定义一个简单的类。如car类

在car.h中,我们做如下声明


#import <Foundation/Foundation.h>


@interface Car : NSObject <NSCopying>

@property (nonatomic,copy)NSString * brand;

@property(nonatomic,assign)int speed;

+(id)carBrand:(NSString*)brand withSpeed:(int)speed;

@end


在car.m文件中

//

//  Car.m

//  CopyAndMutableCopy

//

//  Created by 肖俊全 on 15/3/3.

//  Copyright (c) 2015 肖俊全. All rights reserved.

//


#import "Car.h"


@implementation Car

+(id)carBrand:(NSString *)brand withSpeed:(int)speed{

    Car * car=[[[[self class] alloc ]init]autorelease];

    car.brand =brand;

    car.speed= speed;

    return car;

}


-(id)copyWithZone:(NSZone *)zone{

    //如果子类拷贝,则一定要写【self class

    Car *copy = [[self class]allocWithZone:zone];//这里内存不用释放。因为后面会调用coy release方法

    

    copy.brand=self.brand;

    copy.speed=self.speed;

    return copy;

}

-(void)dealloc{

    [_brand release];

    

    NSLog(@"%@被回收了",self.brand );

    [super dealloc];

  

}

-(NSString *)description{

    

    return [NSString stringWithFormat:@"brand is %@,speed is %i",_brand,_speed];

}


@end


主函数中:


#import <Foundation/Foundation.h>

#import "Car.h"

#import "Bus.h"

#pragma mark carCopy

void carCopy(){

    Car * c1=[Car carBrand:@"baoma" withSpeed:300];

    Car *c2=[c1 copy];

    c2.brand = @"hanma";

    NSLog(@"c1=%@",c1);

    NSLog(@"c2=%@",c2);

    [c2 release];

}



然后在main当中,直接调用carCopy();即可。我们得到。

2015-03-04 11:58:29.727 CopyAndMutableCopy[933:45912] c1=brand is baoma,speed is 300

2015-03-04 11:58:29.728 CopyAndMutableCopy[933:45912] c2=brand is hanma,speed is 300

2015-03-04 11:58:29.728 CopyAndMutableCopy[933:45912] hanma被回收了

2015-03-04 11:58:29.729 CopyAndMutableCopy[933:45912] baoma被回收了

Program ended with exit code: 0



可以看到。我们对c1的copy,得到c2,再对c2的brand品牌属性进行更改并不会改变c1的值。最后对象回收,调用对象的dealloc方法。可知没有资源的泄漏。

如果我们在car的基础之上,再派生出一个之类。并在子类对象间进行拷贝。我们应该怎么做呢。

定义一个bus类。

#import "Car.h"


@interface Bus : Car

@property(nonatomic,copy)NSString * name;

+(id)busBrand:(NSString *)brand withSpeed:(int)speed andName:(NSString *)name;

@end



bus.m文件

#import "Bus.h"


@implementation Bus

+(id)busBrand:(NSString *)brand withSpeed:(int)speed andName:(NSString *)name{

    Bus * bus = [Bus carBrand:brand withSpeed:speed];

    bus.name=name;

    return bus;

}

- (void)dealloc

{

    [_name release];

    [super dealloc];

}


-(id)copyWithZone:(NSZone *)zone{

    //一定要调用父类的方法

    Bus *bus= [super copyWithZone:zone];

    bus.name=self.name;

    return bus;

}

-(NSString *)description{

    return [NSString stringWithFormat:@"brand is %@,speed is %i,name is %@",self.brand,self.speed,self.name];


    

}

@end


主函数中

#pragma mark busCopy

void busCopy(){

    Bus *b1=[Bus busBrand:@"JingGang" withSpeed:200 andName:@"bigJingGang"];

    Bus *b2=[b1 copy];

    b2.name=@"hahaJingGang";

    NSLog(@"b1=%@",b1);

    NSLog(@"c2=%@",b2);

    [b2 release];

}

一样的main函数直接调用busCopy(); 方法运行

得到:

2015-03-04 12:03:24.254 CopyAndMutableCopy[964:50733] b1=brand is JingGang,speed is 200,name is bigJingGang

2015-03-04 12:03:24.255 CopyAndMutableCopy[964:50733] c2=brand is JingGang,speed is 200,name is hahaJingGang

2015-03-04 12:03:24.255 CopyAndMutableCopy[964:50733] JingGang被回收了

2015-03-04 12:03:24.255 CopyAndMutableCopy[964:50733] JingGang被回收了

Program ended with exit code: 0



可以方现。我们并没有在bus.m文件中的dealloc方法中写资源回收。其实这里调用的是super的dealloc方法,因为bus继承自car。

并且,我们看似很容易就实现了子类对象的copy方法。这里需要注意的是。子类如果要用到父类的类方法,以及copy父类的一些属性。则父类中,不能写死,

如写成  Car *copy = [car allocWithZone:zone];  而应该写成  Car *copy = [[self class]allocWithZone:zone];

包括初始化对象的时候应该写成 Car * car=[[[[self classalloc ]init]autorelease];  方便子类调用。使得程序做到低偶合,高内聚。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值