<一>Copy和mutableCopy——iOS开发的疑惑

        许久没写博客,期间一边学习一边工作,非常忙碌,特别是iOS的学习要花很多时间,每天都要码代码,熟悉Xcode的使用,偶尔遇到一些比较大的难题,才会停下来想想怎么解决,最近在看别人源码的时候一直被copy和木tablecopy困扰,网上找的文章写的都挺好,但跟我自己做的实验不大一样,所以记录一下我做的实验结果。

一、问题

        我是看着copy和mutableCopy然后糊涂了,不知道怎么用才搜的答案,而实际使用中为什么要用copy呢?以下是原因:

        比如我们想拿到数组array中的下标为0的对象出来使用,那么就有以下语句:

        id temp = [array objectAtIndex:0];

        而如果我后面不想用这个数组或者不小心删了数组中下标为0的对象后,

        [array removeObjectAtIndex:0];

        上面的temp就没法使用,成了野指针,这时候再用这个temp程序就会崩。


        任何技术的出现都是有理由的,copy和mutableCopy也一样,就是为了解决这里的问题,具体怎么解决继续看后面的介绍。

二、简介

        先交代下copy和mutablecopy的知识,在iOS中遵守了NSCopying协议的类才能使用copy,遵守了NSMutableCopy协议的类才能使用mutableCopy,这两个协议还算比较常见,NSString、NSNumber等基础框架类一般都会有(要是实际使用中不知道可以按住command然后点击相应的类名去看看)。

        如果不遵守这两个协议则不能发送copy和mutableCopy,所以想在自定义的类中实现的话要遵守这个协议,并且实现对应的方法:

  • copy——copyWithZone
  • mutableCopy ——mutableCopyWithZone

三、分类说明

3.1  非容器类的对象

        非容器类对象主要是指NSString、NSNumber、NSData之类,这类对象也有可变和不可变之分。在拷贝之前,需要明白,拷贝的对象是什么,拷贝后要赋值的对象又是什么。我们根据拷贝的对象是什么,可以分为两类,即拷贝的对象是可变(mutable)的还是不可变(imutable)的。

3.1.1  先看看拷贝的对象是不可变对象(imutable)的情况:

        NSString *string = @"Origin";
        NSString *stringCopy = [string copy];
        NSString *stringMCopy = [string mutableCopy];
        NSMutableString *mStringCopy = [string copy];
        NSMutableString *mStringMCopy = [string mutableCopy];
        //[mStringCopy appendString:@"!!"];
        [mStringMCopy appendString:@"!!"];
        
        NSLog(@"string--------%p", string);
        NSLog(@"stringCopy----%p", stringCopy);
        NSLog(@"stringMCopy---%p", stringMCopy);
        NSLog(@"mStringCopy---%p", mStringCopy);
        NSLog(@"mStringMCopy--%p", mStringMCopy);

2015-09-18 11:02:15.098 CopyAndMutableCopyTest[839:51989] string--------0x100001040
2015-09-18 11:02:15.099 CopyAndMutableCopyTest[839:51989] stringCopy----0x100001040
2015-09-18 11:02:15.099 CopyAndMutableCopyTest[839:51989] stringMCopy---0x100206b70
2015-09-18 11:02:15.099 CopyAndMutableCopyTest[839:51989] mStringCopy---0x100001040
2015-09-18 11:02:15.099 CopyAndMutableCopyTest[839:51989] mStringMCopy--0x100206c00

从打印出来的信息可以看到

string--------0x100001040

stringCopy----0x100001040

mStringCopy---0x100001040

这三个都是同个内存地址,而这三个string都是通过[string copy]来赋值的,所以可以知道对非容器类的不可变对象的copy,都是浅拷贝(指针复制)



stringMCopy---0x100206b70

mStringMCopy--0x100206c00

这两个string的内存地址不一样,他们是通过 [string mutableCopy] 来赋值的,所以进行了对象复制,即stringMCopy和mStringMCopy这两个对象都是重新在堆中重新开辟内存然后赋给他们的,而不是简单的指针复制,所以我们可以得到:对非容器类不可变对象的mutableCopy,都是深拷贝(对象复制)


3.1.2  拷贝的对象是可变(mutable)对象的情况:


        NSMutableString *mstring = [NSMutableString stringWithString:@"Origin"];
        NSString *stringCopy = [mstring copy];
        NSString *stringMCopy = [mstring mutableCopy];
        NSMutableString *mStringCopy = [mstring copy];
        NSMutableString *mStringMCopy = [mstring mutableCopy];
        //[mStringCopy appendString:@"!!"];
        [mStringMCopy appendString:@"!!"];
        
        NSLog(@"mstring--------%p", mstring);
        NSLog(@"stringCopy----%p", stringCopy);
        NSLog(@"stringMCopy---%p", stringMCopy);
        NSLog(@"mStringCopy---%p", mStringCopy);
        NSLog(@"mStringMCopy--%p", mStringMCopy);

2015-09-18 11:04:13.295 CopyAndMutableCopyTest[847:53197] mstring--------0x100206b30
2015-09-18 11:04:13.296 CopyAndMutableCopyTest[847:53197] stringCopy----0x6e696769724f65
2015-09-18 11:04:13.296 CopyAndMutableCopyTest[847:53197] stringMCopy---0x100206c80
2015-09-18 11:04:13.296 CopyAndMutableCopyTest[847:53197] mStringCopy---0x6e696769724f65
2015-09-18 11:04:13.297 CopyAndMutableCopyTest[847:53197] mStringMCopy--0x100206cc0

从打印出来的信息可以看到

stringCopy----0x6e696769724f65

mStringCopy---0x6e696769724f65

这两个string是通过[string copy]赋值的,但是!!这个地址已经和拷贝的主体mstring的地址不一样了,mstring--------0x100206b30,所以对于非容器类的可变对象的copy,都是深拷贝(对象复制)。



stringMCopy---0x100206c80

mStringMCopy--0x100206cc0

这两个string是通过[string mutableCopy]赋值的,但是这两个地址不一样,可以看到是递增的,从c80增加到cc0,那么我们可以得出结论,对于非容器类的可变对象的mutableCopy,都是深拷贝(对象复制)。

这时候的[string copy] 和 [string mutableCopy]的区别也显而易见,

通过[string copy]拷贝出来的地址都是同一个0x6e696769724f65

而通过[string mutableCopy]拷贝出来的地址则会变化。

这就是在非容器类的可变对象的进行copy和mutableCopy后的区别。实际使用中还是当然还是建议大家用mutableCopy了。


注:不管是可变还是不可变对象的copy,当其赋值给mutable对象时,这个对象指向的内容是不可变的。举例子:上面的

        //[mStringCopy appendString:@"!!"];
这一句编译能通过,但是运行时就会崩。所以请留意copy后的对象是不可变的,不要赋值给可变的对象。




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值