【学习ios之路:Objective-C】深拷贝和浅拷贝

深浅拷贝的区别:

深拷贝   拷贝  内容

浅拷贝  拷贝  地址

注:当对象str1在常量区时

①对不可变字符串NSString对象进行copy

        NSString *str1 = @"Hello"; //str1 -- 常量区
        NSLog(@"%p", str1);//0x100002048
        //copy
        NSString *str2 = [str1 copy];//0x100002048 str2 -- 常量区
        NSLog(@"%p", str2);//str2 与 str1都指向常量区,地址相同,引用计数为无穷大
        NSLog(@"str2 retaincount = %lu", [str2 retainCount]);<span style="font-size:18px;">//18446744073709551615</span>

②对不可变字符串NSString对象进行mutableCopy

        //mutableCopy,深拷贝,拷贝内容,而且拷贝出来的是一个可变的对象
        NSMutableString *str3 = [str1 mutableCopy];
        NSLog(@"str3 retaincount = %lu", [str3 retainCount]);//1
        [str3 appendString:@"world"];//对拷贝出来的对象进行操作
        NSLog(@"str3 = %@", str3);

注:当对象str1在堆区时

        NSString *str1 = [NSString stringWithFormat:@"Frank"];
        NSLog(@"str1 = %p, retaincount = %lu", str1, [str1 retainCount]);//1

①对不可变字符串NSString对象进行copy

        //copy, 浅拷贝, 拷贝 地址, 并且将原有对象的引用计数加1.
        NSString *str2 = [str1 copy];// str2与str1指向同一块堆区空间
        NSLog(@"str2 = %p, retaincount = %lu", str2, [str2 retainCount]);//2

②对不可变字符串NSString对象进行mutableCopy

        //mutableCopy,深拷贝,拷贝内容,堆区开辟新的空间,并且拷贝出来的对象是可变的.
        NSMutableString *str3 = [str1 mutableCopy];//str3与str1指向不同的对象
        [str3 appendString:@"lanou"];
        NSLog(@"str3 = %p, retaincount = %lu", str3, [str3 retainCount]);//1

可变字符串(NSMutableString)

①对一个可变字符串NSMutableString对象copy

        //原有对象str1在堆区
        NSMutableString *str1 = [[NSMutableString alloc] initWithFormat:@"Frank"];
        NSLog(@"str1 = %p", str1);//0x10010b800
        //copy 堆区中开辟新的空间,拷贝内容到新的空间上,但是拷贝出来的是不可变字符串对象.
        NSString *str2 = [str1 copy];
        NSLog(@"str2 = %p, retaincount = %lu", str2, [str2 retainCount]);//1

②对一个可变字符串NSMutableString对象mutableCopy

        //mutableCopy 堆区中开辟新的空间,拷贝内容到新的空间上,但是拷贝出来的是可变字符串对象.
        NSMutableString *str3 = [str1 mutableCopy];
        [str3 appendString:@"lanou"];
        NSLog(@"str3 = %p, retaincount = %lu", str3, [str3 retainCount]);

总结:

        /**
         *  总结:拷贝是分为可变对象与不可变对象.
            浅拷贝 ---  只拷贝对象地址,不会拷贝内容,不会开辟新的空间.
            深拷贝 ---  拷贝内容,堆区开辟新的空间.
            不可变对象: 1.copy 相当于retin, 原有对象引用计数加1,拷贝地址.
                     2.mutableCopy 复制出新的对象,并且对象是可变的,开呗内容.
            可变对象: 1.copy 复制出新的对象,但是对象是不可变的,拷贝内容.
                     2.mutableCopy 复制出新的对象,但是对象是可变的,拷贝内容.
         */

③.对一个自定义对象Copy和mutableCopy,需要服从<NSCopying, NSMutableCopying>协议,例如:

1.创建Person.h

@interface Person : NSObject <NSCopying, NSMutableCopying>
@property (nonatomic, copy) NSString *name; //姓名
@property (nonatomic, copy) NSString *gender; //性别
@property (nonatomic) NSInteger age;//年龄
@end

2.Person.m文件服从协议

@implementation Person

- (id)copyWithZone:(NSZone *)zone
{
    Person *newPerson = [[[self class] allocWithZone:zone] init];
    newPerson.name = [self.name copy];
    newPerson.gender = [self.gender copy];
    newPerson.age = self.age;
    return newPerson;
}

- (id)mutableCopyWithZone:(NSZone *)zone
{
    Person *newPerson = [[[self class] allocWithZone:zone] init];
    newPerson.name = [self.name mutableCopy];
    newPerson.gender = [self.gender mutableCopy];
    newPerson.age = self.age;
    return newPerson;
}

- (void)dealloc
{
    self.name = nil;
    self.gender = nil;
    [super dealloc];
}
@end

实现,对深浅拷贝分析

       //Person copy 与 mutableCopy
        NSString *name = [NSString stringWithFormat:@"Wang"];
        NSString *gender = [NSString stringWithFormat:@"Man"];

        Person *per = [[Person alloc] init];
        per.name = name;
        per.gender = gender;
        NSLog(@"per = %p", per);//0x10010b980

        //per name = 0x100100560, gender = 0x100104ac0(拷贝前地址)
        NSLog(@"per name = %p, gender = %p", per.name, per.gender);

        Person *copyPerson = [per copy];

        //copyPerson = 0x100500a90, retaincount = 1(拷贝后地址)
        NSLog(@"copyPerson = %p, retaincount = %lu",
                                     copyPerson, [copyPerson retainCount]);
        //(拷贝后内容地址不变,把地址拷贝过去)
        //copyPerson name = 0x100100560, gender = 0x100104ac0
        NSLog(@"copyPerson name = %p, gender = %p",
                                      copyPerson.name, copyPerson.gender);

        Person *mutaCopyPerson = [per mutableCopy];

        //copymutaCopyPersonPerson = 0x100401d50, retaincount = 1
        NSLog(@"copymutaCopyPersonPerson = %p,
                retaincount = %lu", mutaCopyPerson, [mutaCopyPerson retainCount]);
         //(mutableCopy)地址不同,即拷贝是内容
        //mutaCopyPerson name = 0x100401450, gender = 0x1004014e0
        NSLog(@"mutaCopyPerson name = %p, gender = %p",
                mutaCopyPerson.name, mutaCopyPerson.gender);
时间: 2024-08-29 23:28:01

【学习ios之路:Objective-C】深拷贝和浅拷贝的相关文章

【学习ios之路:UI系列】iOS沙盒机制,文件读取,归档与反归档

1.IOS中的沙盒机制 IOS中的沙盒机制是一种安全体系,它规定了应用程序只能在为该应用创建的文件夹内读取文件,不可以访问其他地方的内容.所有的非代码文件都保存在这个地方,比如图片.声音.属性列表和文本文件等. 特点: 1.每个应用程序都在自己的沙盒内 2.不能随意跨越自己的沙盒去访问别的应用程序沙盒的内容 3.应用程序向外请求或接收数据都需要经过权限认证 每个沙盒含有3个文件夹:Documents, Library 和 tmp.Library包含Caches.Preferences目录.如下图

【学习ios之路:Object-C】类与对象

1.面向对象和面向过程概念 1).面向过程 面向过程:以过程为核心,注重的是完成事件的详细步骤,一步一步如何实现. 2).面向对象 面向对象:以事物为核心,注重的是参与该事件的事物应该具备的功能.所以完成该事件只是事物所有功能中的一个功能. 2.类与对象 类: 类是具有相同特征以及行为的事物的抽象,它是一个抽象的概念,不具体. 对象: 类的实例.类的具体体现.生活中的万物都是对象. 3.OO与OOP OO:(Object Oritented)面向对象 OOP:(Object Oriented P

【学习ios之路:C语言】指针

指针 1.指针定义,即简单用法. <span style="font-size:14px;"> //指针变量:专门用来存储地址的变量. int *p = NULL;//NULL == 0 /** * 变量定义时: * (int *):指针类型 * p: 变量名 NULL:初始值. * NULL(指向了一个无效的区域) * *的作用: 告诉编译器,后面变量是指针变量,用来存储地址. * int作用: 1.当通过指针变量取数据时,一次性读取几个字节的数据. 2.当指针变量+1时

【学习ios之路:Object-C】NSString和NSArray

1.字符串 *   字符串常用方法 *   字符串创建方法(最常用) *   字符串追加方法 *   求子串 以及字符串中取某个字符 *   字符替换 *   字符串与其他转换(经常用) *   字符串改变大小写 *   字符串比较方法(经常用) 例如: 1).创建一个字符串对象方法: NSstring * str1 = @"hello"; //1.直接赋值 //2.通过initWithString NSString * str = [[NSString alloc]initWithS

【学习ios之路:UI系列】UIProgressView

实现类似读取数据进度条效果 代码如下: ①创建UIProgressView对象 1)定义属性 { NSTimer *_proTimer;//计时 } @property (nonatomic, retain) UIProgressView *proView; //显示进度信息 @property (nonatomic, retain) UILabel *proLabel; @property (nonatomic, assign) float proValue;//保存进度值 //创建控件UIP

【学习ios之路:UI系列】点击更换头像实现从相册读取照片和拍照两种功能

功能如下: 1.点击头像,提示选择更换头像方式①相册 ②照相. 2.点击相册,实现通过读取系统相册,获取图片进行替换. 3.点击照相,通过摄像头照相,进行替换照片. 4.如果摄像头,弹出框警告. 代码如下: 1.通过UIActionSheet对象实现提示功能 //创建对象 UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle: @"提示" delegate:self cancelButtonTitle:@&q

【学习ios之路:Objective-C】OC中常用的系统排序方法

①.OC中常用排序方法: 1).不可变数组 - (NSArray *)sortedArrayUsingSelector:(SEL)comparator; - (NSArray *)sortedArrayUsingComparator:(NSComparator)cmptr; 2)可变数组 - (void)sortUsingSelector:(SEL)comparator; - (void)sortUsingComparator:(NSComparator)cmptr; 3).字典排序 - (NS

【学习ios之路:UI系列】NSPredicate相关用法

NSPredicate NSPredicate是一个Foundation类,它指定数据被获取或者过滤的方式. 它的查询语言就像SQL的WHERE和正则表达式的交叉一样,提供了具有表现力的,自然语言界面来定义一个集合被搜寻的逻辑条件. NSPredicate的几种用法 ①常见形式 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'zhangdan'"]; //注意:如果谓词串中的文本块未被引用,则被看

【学习ios之路:UI系列】实现轮播图效果(UIImageView,UIScrollView,UIPageControl,NSTimer相结合)

实现效果,在不点击的情况下,自定滚动,点击时,停止.如下图 部分代码如下: //调用NSTimer方法,自定计时 - (void)autoScroll { self.timer = [NSTimer scheduledTimerWithTimeInterval:1.5 target:self  selector:@selector(scrollToRight) userInfo:nil repeats:YES]; } //实现触发方法 - (void)scrollToRight { [UIVie