Objective-C copy

本文深入探讨了深拷贝和浅拷贝的概念,包括它们在Objective-C中的实现方式,如NSCopying和NSMutableCopying协议,以及如何影响NSString和NSMutableString等不同类型的对象。同时,文章还讨论了在使用copy和strong修饰符时的注意事项,特别是在处理可变对象时。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

copy:
copy/mutableCopy 是通过NSCopying/NSMutableCopying实现的

浅/深copy(区别: 原对象和副本的指针是不是指向同一地址)
浅复制:复制对象的指针,两个指针指向同一个对象。
深复制:复制对象本身, 复制后的对象和被复制的对象相互独立,互补影响。

修饰关键字 copy

可以copy的对象都遵守NSCopying/NSMutableCopying
NSCopying/NSMutableCopying 协议方法
NSZone

//NSCopying
- (id)copyWithZone:(nullable NSZone *)zone;
//NSMutableCopying
- (id)mutableCopyWithZone:(nullable NSZone *)zone;
//对象的复制方法
-(id)copy;
-(id)mutableCopy;

深/浅copy
容器类(容器中存放对象的指针需区分对待)和其他类

其他对象:
NSString string类型在许多语言中都被特殊处理

	NSString *string1 = [NSString stringWithFormat:@"string1"];
    NSString *string2 = string1.copy;
    NSMutableString *string3 = string1.mutableCopy;
    NSLog(@"string1 : %@ %@, %p", string1.class, string1, string1);
    NSLog(@"string2 : %@ %@, %p", string2.class, string2, string2);
    NSLog(@"string3 : %@ %@, %p", string3.class, string3, string3);

在这里插入图片描述

NSString
string1和string2地址是同一个 在NSString中copy是浅copy
string3是重新传家的地址 在NSString中mutableCopy是深copy

插入一个知识点
__NSCFConstantString, __NSCFString, NSTaggedPointerString,
__NSCFConstantString 是字符串常量 app生命周期结束前不会释放

//创建方式
NSString *string = @"123";

__NSCFString 是NSString的子类,和普通类型一样受系统内存回收机制管理

//创建方式
NSString *string = [NSString stringWithFormat:@"string1"];

NSTaggedPointerString
标签指针类型,内部优化 在64位系统中指针在内存中的大小是8位,可以存放一些比较小的字符串;系统会根据string的大小来自动创建NSTaggedPointerString,就是当string长度小于9位创建的类型是NSTaggedPointerString,长度大于9是__NSCFString。(9是自己测试出来的,没有具体的文档描述);

NSMutableString

	NSMutableString *string1 = [NSMutableString stringWithFormat:@"string"];
    NSString *string2 = string1.copy;
    NSMutableString *string3 = string1.mutableCopy;
    NSLog(@"string1 : %@ %@, %p", string1.class, string1, string1);
    NSLog(@"string2 : %@ %@, %p", string2.class, string2, string2);
    NSLog(@"string3 : %@ %@, %p", string3.class, string3, string3);

在这里插入图片描述
NSMutableString
copy/mutableCopy 都是深copy

继承自NSObject的类(需要遵守NSCopying协议)

//浅copy
#import "copyObject.h"
@implementation copyObject
-(id)copyWithZone:(NSZone *)zone{
    return self;
}
@end

//深copy
#import "copyObject.h"
@implementation copyObject
-(id)copyWithZone:(NSZone *)zone{
    copyObject *object = [[copyObject alloc]init];
    object.name = @"object";
    return object;
}
@end

容器类
NSArray

	NSObject *object1 = [[NSObject alloc]init];
    NSObject *object2 = [[NSObject alloc]init];
    NSObject *object3 = [[NSObject alloc]init];
    NSArray *array1 = @[object1, object2, object3];
    NSArray *array2 = array1.copy;
    NSMutableArray *array3 = array1.mutableCopy;
    NSLog(@"array1 : %@ %@, %p", array1.class, array1, array1);
    NSLog(@"array2 : %@ %@, %p", array2.class, array2, array2);
    NSLog(@"array3 : %@ %@, %p", array3.class, array3, array3);

在这里插入图片描述
__NSarrayI 不可变数组 __NSArrayM可变数组
NSArray
copy 浅copy
MutableCopy 深copy
数组中的元素并没有copy

NSMutableArray

	NSObject *object1 = [[NSObject alloc]init];
    NSObject *object2 = [[NSObject alloc]init];
    NSObject *object3 = [[NSObject alloc]init];
    NSMutableArray *array1 = [NSMutableArray array];
    [array1 addObject:object1];
    [array1 addObject:object2];
    [array1 addObject:object3];
    NSArray *array2 = array1.copy;
    NSMutableArray *array3 = array1.mutableCopy;
    NSLog(@"array1 : %@ %@, %p", array1.class, array1, array1);
    NSLog(@"array2 : %@ %@, %p", array2.class, array2, array2);
    NSLog(@"array3 : %@ %@, %p", array3.class, array3, array3);

在这里插入图片描述
NSMutableArray
copy/mutableCopy 都是深copy
数组中的元素并没有copy

修饰关键字 copy
在原对象不可变的情况下 使用copy/strong修饰并没有差别

在原对象为可变的情况下
修饰不可变对象

//声明
@property (nonatomic, copy) NSString *nameCopy;
@property (nonatomic, strong) NSString *nameStrong;

//操作
NSMutableString *string = [NSMutableString stringWithFormat:@"name"];
self.nameStrong = string;
self.nameCopy = string;
[string appendString:@"a"];
NSLog(@"string : %@ %@, %p", string.class, string, string);
NSLog(@"self.nameCopy : %@ %@, %p", self.nameCopy.class, self.nameCopy, self.nameCopy);
NSLog(@"self.nameStrong : %@ %@, %p", self.nameStrong.class, self.nameStrong, self.nameStrong);

在这里插入图片描述
strong 修饰不可变对象 和 原对象指向同一地址,随着原对象改变而改变 (数据不稳定)
copy修饰不可变对象 copy一份 原对象改变不影响 copy的对象

修饰可变对象
使用strong和copy修饰和修饰不可变对象一样 strong修饰指向同一地址 copy修饰创建新对象

	NSMutableString *string = [NSMutableString stringWithFormat:@"name"];
    self.nameStrong = string;
    self.nameCopy = string;
    [string appendString:@"a"];
    NSLog(@"string : %@ %@, %p", string.class, string, string);
    NSLog(@"self.nameCopy : %@ %@, %p", self.nameCopy.class, self.nameCopy, self.nameCopy);
    NSLog(@"self.nameStrong : %@ %@, %p", self.nameStrong.class, self.nameStrong, self.nameStrong);

注意 self.nameCopy 类型由NSMutableString-> NSString
一般很少使用NSMutableString;在NSMutableArray上也是类似,如果对NSMutableArray使用copy有可能导致类型变为NSArray,进而进行增删改功能导致crash。
在这里插入图片描述

block 修饰
block 是被创建在栈上的
ARC copy和strong修饰 block 都会被从栈区复制到堆区
MRC copy会把block从栈区复制到堆区并且对block中使用的外部对象进行retain操作
retain并不会保存在block中使用的外部对象,当超出block所在的作用域时,调用block, block使用外部对象(此时若对象已被释放)是会造成crash。

个人知识记录

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值