NSCopying和NSMutableCopying协议

作者: 黄龙辉 | 来源:发表于2015-09-23 09:22 被阅读10701次

    NSCopying

    NSCopying是一个与对象拷贝有关的协议。如果想让一个类的对象支持拷贝,就需要让该类实现NSCopying协议。NSCopying协议中的声明的方法只有一个- (id)copyWithZone:(NSZone *)zone。当我们的类实现了NSCopying协议,通过类的对象调用copy方法时,copy方法就会去调用我们实现的- (id)copyWithZone:(NSZone *)zone方法,实现拷贝功能。实现代码如下所示:

    - (id)copyWithZone:(NSZone *)zone{    
         PersonModel *model = [[[self class] allocWithZone:zone] init];
         model.firstName = self.firstName;
         model.lastName  = self.lastName;
         //未公开的成员
         model->_nickName = _nickName;
         return model;
    }
    

    说明:在- (id)copyWithZone:(NSZone *)zone方法中,一定要通过[self class]方法返回的对象调用allocWithZone:方法。因为指针可能实际指向的是PersonModel的子类。这种情况下,通过调用[self class],就可以返回正确的类的类型对象。

    NSMutableCopying

    NSCopying协议与NSMutableCopying的区别主要是在于,返回的对象是否是可变类型的。以Foundation框架的NSArray为例

    NSArray *nameArray = @[@"Jim", @"Tom", @"David"];
    NSArray *copyArray = [nameArray copy];
    NSMutableArray *mutableCopyArray = [nameArray mutableCopy];
    [mutableCopyArray addObject:@"Sam"];
    

    NSArray对象调用copy方法时,copy方法会调用- (id)copyWithZone:(NSZone *)zone,得到对象的一份拷贝,但得到的对象还是不可变的对象。而NSArray对象调用mutableCopy方法时,mutableCopy方法会调用- (id)mutableCopyWithZone:(NSZone *)zone,得到可变的对象。

    所以,如果自定义类具有可变和不可变的区别,想让它支持拷贝时,就需要同时实现NSCopyingNSMutableCopying,在- (id)copyWithZone:(NSZone *)zone返回的是不可变对象,在- (id)mutableCopyWithZone:(NSZone *)zone返回的是可变对象。

    在拷贝对象时,需要注意拷贝执行的是浅拷贝还是深拷贝。深拷贝在拷贝对象时,会将对象的底层数据也进行了拷贝。Foundation框架中提供的所有集合,默认提供的都是浅拷贝。以上面的代码为例,对nameArray执行copy时,得到一个新的数组对象。但是新对象中存放的字符串和nameArray中存放的都是同一个字符串;若执行的是深拷贝,就会对nameArray中的所有字符串执行copy操作,然后再加入到新的对象中。

    相关文章

      网友评论

      • 提莫不想打团战:文章最后一段的:“以上面的代码为例,对nameArray执行copy时,得到一个新的数组对象。”

        NSArray *array0 = [[NSArray alloc] init];
        NSArray *array1 = [array0 copy];
        NSLog(@"%p,%p",array0,array1);

        打印出来两个的地址是一样的,并没有产生新的对象。
        4002796ae144:@Simon_wang 这个你可以打印一下看看啊,元素地址我没细究。如果元素地址与原数组内元素地址一样,那还拷贝它干啥。深拷贝不彻底,就不算真正的深拷贝。讲道理地址应该是不一样的。
        Simon_____:@艾欧尼亚_99da “如果copy的是NSMutableArray,那么你就会发现新拷贝的数组的地址与原数组地址不一样了”,
        数组地址是不一样了,但是里面元素如果是不可变类型的对象的地址又是一样的?
        4002796ae144:因为NSArray是不可变类型数组,所以为了节省内存,copy后的新指针也会指向同一内存地址。如果copy的是NSMutableArray,那么你就会发现新拷贝的数组的地址与原数组地址不一样了。同样适用于NSString与NSMutableString。
      • 经天纬地:以上面的代码为例,对nameArray执行copy时,得到一个新的数组对象。但是新对象中存放的字符串和nameArray中存放的都是同一个字符串;若执行的是深拷贝,就会对nameArray中的所有字符串执行copy操作,然后再加入到新的对象中。


        这句能说清楚点吗?怎么读起来好像是同一个意思?
        WeightZhang:@艾欧尼亚_99da 有原则性错误而已
        经天纬地:@艾欧尼亚_99da :smile:
        4002796ae144:别问了,博主也是抄来的,毛都不懂。。。

      本文标题:NSCopying和NSMutableCopying协议

      本文链接:https://www.haomeiwen.com/subject/cpmicttx.html