• Objective -C学习笔记 之copy(复制)


    //自定义类对象实现copy需要遵守copy协议(否则程序崩溃),实现必须实现的协议方法,里面的代码就决定了你的copy是深是浅
     1 #import <Foundation/Foundation.h>
     2 #import "Student.h"
     3 
     4 //接口部分
     5 // @interface Student : NSObject//<NSCopying/*copy协议*/,NSCoding/*归档协议*/>
     6 //
     7 //@property(nonatomic,copy)NSString *name;
     8 //@property(nonatomic,assign)int Age;
     9 //
    10 //@end
    11 
    12 int main(int argc, const char * argv[])
    13 {
    14     @autoreleasepool
    15     {
    16         Student *student = [[Student alloc] init];
    17         student.name = @"liuguan";
    18         student.Age = 21;
    19         NSLog(@"%@",student);
    20         Student *student1 = [student copy];//深复制
    21         //协议实现方式
    22         /***************************
    23          //如果直接return self,则是浅拷贝,如果使用alloc,则是深拷贝
    24          - (id)copyWithZone:(NSZone *)zone
    25          {
    26          Student *stu = [Student allocWithZone:zone];
    27          //    Student *stu = [[[[self class] allocWithZone:zone]init]autorelease];// ARC
    28          //    stu.name = self.name;
    29          //    stu.Age = self.Age;
    30          stu.name = [self.name copy];
    31          stu.Age = self.Age;
    32          NSLog(@"%p***%p",stu.name,self.name);//0x100002078***0x100002078地址一致(浅copy)
    33          return stu;
    34          }//相当于stu的地址等于self的地址,但是这个地址是新开辟的,所以跟copy接收者就没关系了
    35          ***************************/
    36         
    37         
    38      //Student *student1 = [student copy];//浅复制
    39      
    40       //  协议实现方式
    41         /*************************
    42          //- (id)copyWithZone:(NSZone *)zone
    43          //{
    44          //    return self;//直接相等
    45          //}//相当于self的地址直接等于copy接受者的地址
    46          相当于 Student *student1 = student ;
    47          ***************************/
    48         student1.name = @"wangxinag";
    49         NSLog(@"%@",student1);
    50         NSLog(@"%@",student);
    51     }
    52     return 0;
    53 }

    在这里首先提及的就是定义属性是用的属性列表中的copy

    @property(nonatomic,copy)NSString *name;

    在这里我定义了一个Person类,此处不再陈述

    下面是代码

            Person *p = [[Person alloc] init];

            NSMutableString *s = [[NSMutableString alloc] initWithFormat:@"123"];     

            p.name = s;   //此时,name的值为@"123"

            NSLog(@"**%@",p.name);

            [s appendString:@"world"];

            NSLog(@"%@",p.name);

            NSLog(@"%p---%p",s,p.name);

    输出结果:

    **123

    123

    0x100206e00---0x100206cf0

    可以看出可变字符串的值赋给了属性name,但是地址变化了,在第一次输出123后边我又对s进行了重新赋值为world,但是并未影响到p.name的值,这也就验证了地址确实不同了。其实它内部是通过

    - (void)setName:(NSMutableString *)name

    {

     if(_name != name){          //判断是否需要重新赋值

          [_name release];        //释放旧引用,计数器-1

          _name = [name copy];   //重新赋值,使用copy********就是这里*********

       }

    }

    进行了深复制。因为s是可变数组,所以copy之后会开辟一个新的地址空间。假如s是不可变数组,那么就会进行浅复制

    假如把代码改成:

            Person *p = [[Person alloc] init];

            NSString *s = @"123";     

            p.name = s;   //此时,name的值为@"123"

            NSLog(@"%@",p.name);

            NSLog(@"%p---%p",s,p.name);

    输出结果:

    123

    0x100001068---0x100001068

    地址是一样的,说明进行了浅复制

    总结:

    copy:浅拷贝:不产生新的对象,直接指向原有对象(地址数据相同,虽然指针的名字不同)
        拷贝出的结果是不可变对象,跟其接受类型没有关系,跟其传入类型也没有关系
    mutableCopy:深拷贝:产生新的对象,其内容是原有对象的内容,地址变了
        拷贝的结果是可变对象,跟其传入的类型没有关系,但是会受其接收类型的影响
    copy:被复制着是可变,则为深,否则为浅

    NSString *s2 = [s1 copy];//八种情况中(s1:mutableString/String;s2:mutableString/String;copy/mutableCopy),只有s1为不可变和利用copy方法  同时满足时为浅复制,其余为深复制 

    //当使用NSCopy复制一个不可变对象时,其行为是浅复制,其余情况都是深拷贝
    //当使用NSMutablecopy时,是深拷贝

    那么为什么浅复制地址不变呢?

            当被copy者类型是字符串常量时(就是不可变字符串),系统会为我们优化,声明了多个字符串,
            但是都是常量,且内容相等,那么系统就只为我们申请一块空间。
    赋值过程:输入数据→寄存器处理→开辟内存→写入数据。一次深复制,可以得到被复制对象指针,并进行一次赋值操作。
  • 相关阅读:
    RBAC权限管理模型 产品经理 设计
    Redisson 分布式锁
    Jenkins下载历史Build版本的归档文件
    Java JPA @Transient 在Hibernate中应用
    Solving the Top ERP and CRM Metadata Challenges with erwin & Silwood
    MySQL 字符串 分割 多列
    MySQL CONCAT opposite
    Web并发页面访问量统计实现
    UNIX网络编程读书笔记:基本UDP套接口编程
    UNIX网络编程调试工具:tcpdump、netstat和lsof
  • 原文地址:https://www.cnblogs.com/liuguan/p/4931933.html
Copyright © 2020-2023  润新知