iOS的各种拷贝

熟悉了内存的分配方式的一些基础知识后,接下来就是关于copy和mutableCopy了。
对一个不可变数组进行copy,返回的实际是自身,对一个不可变数组进行mutableCopy,会产生一个新的可变数组。
在OC中,所有的对象的copy和mutableCopy,都是分别遵循了NSCopy和NSMutableCopy协议,需要对应实现的方法就是 - (id)copyWithZone:(NSZone *)zone- (id)mutableCopyWithZone:(NSZone *)zone

  1. 系统容器类 如:NSString、NSArray、NSDictionary等,他们已经遵循了上面的两个协议,并且实现了上面两个方法
		NSString *Str = @"123";
       	NSString *newStr = [Str copy];
        /*NSString *st = [Str mutableCopy];*/
        id st = [Str mutableCopy];

对于它们来说,规则很简单
obj2 = [obj1 copy]返回的必然是一个不可变对象
obj2 = [obj1 mutableCopy]返回的必然是一个可变对象,无论obj1是可变对象还是不可变对象。即使obj1也是一个可变对象,它们仍指向不同地址,是两个对象。
一个简单的分析

// 关于深浅拷贝的探究
- (void)testCopy {
    // 对不可变string 拷贝
    NSString *baseString = @"a new string";
    NSString *copyStr = [baseString copy];
    NSMutableString *mutableCopyString = [baseString mutableCopy];
    
    NSLog(@"------%p \n %p \n %p",baseString,copyStr, mutableCopyString);
    /**
     0x1057b10b8
     0x1057b10b8
     0x600000b86d90
     */
    
    // 对可变对象拷贝
    NSMutableString *mutableBaseString = [[NSMutableString alloc] initWithString:@"test string"];
    NSString *sCopyString = [mutableCopyString copy];
    NSMutableString *sMutableCopyString = [mutableCopyString mutableCopy];
    NSLog(@"------%p \n %p \n %p",mutableBaseString,sCopyString, sMutableCopyString);
    /**
     0x6000007a8c90
     0x6000009e3be0
     0x6000007a8ba0
     */
}

**
不可变对象的copy方法进行了浅拷贝
不可变对象的mutableCopy方法进行了深拷贝
可变对象的copy方法进行了深拷贝
可变对象的mutableCopy方法进行了深拷贝。
**

  1. 自定义类
    因为是自定义类 copyWithZone:和mutableCopyWithZone:完全由自己实现,所有代码的实现不同也就决定了返回对象是什么

The returned object is implicitly retained by the sender, which is responsible for releasing it. The copy returned is mutable whether the original is mutable or not.

分析 实现源码

NSString copy
-(id)copyWithZone:(NSZone )zone {
if (NSStringClass == Nil)
NSStringClass = [NSString class];
return RETAIN(self);
}
-(id)mutableCopyWithZone:(NSZone
)zone {
return [[NSMutableString allocWithZone:zone] initWithString:self];
}

NSMutableString copy
-(id)copy {
return [[NSString alloc] initWithString:self];
}
-(id)copyWithZone:(NSZone*)zone {
return [[NSString allocWithZone:zone] initWithString:self];
}

NSMutableString 没有实现mutableCopyWithZone: 但是他继承NSObject 所以会调用父类的mutableCopyWithZone:方法

NSObject copy
-(id)copy {
return [(id)self copyWithZone:nil];
}
-(id)mutableCopy {
return [(id)self mutableCopyWithZone:nil];
}

NSArray,NSDictionary,NSSet 这些容器都类似,就不一一叨叨了。

Question:
NSString类型的成员变量的修饰属性用copy还是strong呢?
成员变量用copy修饰和用strong修饰的区别:如果使用了copy修饰符,那么在给成员变量赋值的时候就会对被赋值的对象进行copy操作,然后再赋值给成员变量。如果使用的是strong修饰符,则不会执行copy操作,直接将被赋值的变量赋值给成员变量
如果成员变量一直保持的是NSString类型,copy和strong肯定是没有区别的
但是,由于OC的特性,虽然成员变量在编译器编译的时候是保持着NSString类型,但是如果
执行下面的操作,当mutableString的值发生了改变后,baseString的值也随之发生改变

NSMutableString *mutableString = [[NSMutableString alloc] initWithString:@“Steven”];
self.baseString = mutableString;
[mutableString appendString:@" Kyle"];

所有为了避免这种不确定性因素,最好还是使用copy修饰

<think>好的,我现在需要回答用户关于iOS深浅拷贝的问题。首先,我得确保自己理解深浅拷贝的基本概念,以及在iOS中的具体实现和应用场景。 首先,深拷贝和浅拷贝的区别是什么?浅拷贝应该是指复制对象的指针,而不是实际数据,所以新旧对象共享同一份数据。而深拷贝则是完全复制数据,新对象和原对象独立,修改互不影响。这在内存管理中很重要,尤其是在处理集合类型如NSArray、NSDictionary时。 接下来,我需要考虑在iOS中,哪些对象默认是浅拷贝,哪些支持深拷贝。比如,使用copy方法时,不可变对象如NSArray可能返回自身(浅拷贝),而可变对象如NSMutableArray会生成新的不可变副本。但这里的copy是否是深拷贝呢?可能要看具体类的实现,比如集合的copy方法是否是浅拷贝,而深拷贝可能需要使用其他方法,比如NSKeyedArchiver。 然后,要提到NSCopying协议,因为自定义对象要实现拷贝功能必须遵循这个协议,并实现copyWithZone:方法。这里可能需要区分浅拷贝和深拷贝的实现方式,比如在复制属性时是直接赋值(浅)还是创建新实例(深)。 还需要举例说明,比如NSString、NSArray等系统类的情况,以及自定义类如何处理。同时,可能需要注意可变和不可变版本的区别,比如NSMutableArray的copy和mutableCopy的不同行为。 另外,内存管理方面,ARC自动处理引用计数,但理解深浅拷贝对内存的影响仍然重要,避免不必要的内存泄漏或重复数据。 可能用户还想知道如何选择深拷贝或浅拷贝,比如在需要独立数据时使用深拷贝,否则使用浅拷贝节省内存。同时,可以提到常见的深拷贝方法,如归档解档(NSKeyedArchiver)、手动复制每个元素等。 最后,检查是否有遗漏点,比如集合对象的元素是否被深拷贝。例如,NSArray的copy是浅拷贝,所以内部的元素还是原来的,如果元素是可变对象,修改它们会影响新旧数组。这时候需要实现真正的深拷贝可能需要遍历每个元素进行复制。 总结回答的结构应该包括:定义、区别、系统类的行为、自定义类的实现、深浅拷贝的选择以及注意事项。确保用中文,结构清晰,例子恰当,语法正确,数学公式用指定格式。</think>在 iOS 开发中,**深拷贝(Deep Copy)**和**浅拷贝(Shallow Copy)**是对象复制的两种重要方式,理解它们的区别对内存管理和数据独立性至关重要。 --- ### 1. 基本概念 - **浅拷贝** 仅复制对象的指针,新旧对象**共享同一份底层数据**。修改其中一个对象的内容,另一个会受影响。 **示例**: ```objective-c NSArray *original = @[@1, @2, @3]; NSArray *shallowCopy = [original copy]; // 浅拷贝(不可变对象的 copy 是浅拷贝) ``` - **深拷贝** 完全复制对象及其底层数据,生成**独立的新对象**。修改其中一个对象不会影响另一个。 **示例**: ```objective-c NSArray *original = @[@1, @2, @3]; NSArray *deepCopy = [[NSArray alloc] initWithArray:original copyItems:YES]; // 深拷贝 ``` --- ### 2. 系统类的默认行为 - **不可变对象(如 `NSString`, `NSArray`)** - `copy` 方法返回**浅拷贝**(原对象本身,因不可变无需复制)。 - `mutableCopy` 返回**深拷贝**(生成可变对象)。 - **可变对象(如 `NSMutableString`, `NSMutableArray`)** - `copy` 和 `mutableCopy` 均返回**深拷贝**。 $$ \text{可变性决定拷贝行为:可变对象默认深拷贝,不可变对象默认浅拷贝} $$ --- ### 3. 自定义对象的拷贝 若需支持拷贝,类需遵循 **`NSCopying`** 或 **`NSMutableCopying`** 协议,并实现对应方法: ```objective-c @interface Person : NSObject <NSCopying> @property (nonatomic, copy) NSString *name; @end @implementation Person - (id)copyWithZone:(NSZone *)zone { Person *copy = [[Person alloc] init]; copy.name = self.name; // 浅拷贝(直接赋值指针) return copy; } @end ``` - **浅拷贝实现**:直接赋值属性(共享同一数据)。 - **深拷贝实现**:为每个属性创建新对象(例如 `copy.name = [self.name copy]`)。 --- ### 4. 集合对象的深拷贝陷阱 即使对 `NSArray`/`NSDictionary` 深拷贝,其内部元素的拷贝行为取决于元素类型: - **`copyItems:YES`** 仅对集合元素调用 `copy` 方法,若元素是自定义对象且未实现深拷贝,仍为浅拷贝! **完全深拷贝解决方案**: ```objective-c NSData *data = [NSKeyedArchiver archivedDataWithRootObject:originalArray]; NSArray *trueDeepCopy = [NSKeyedUnarchiver unarchiveObjectWithData:data]; ``` --- ### 5. 如何选择? | 场景 | 推荐方式 | |------|----------| | 对象不可变且无需修改 | 浅拷贝(节省内存) | | 对象需要独立修改 | 深拷贝 | | 集合对象包含可变元素 | 完全深拷贝(如归档解档) | --- ### 6. 注意事项 - 使用 `copy` 修饰符(`@property (copy)`)可防止可变对象被外部修改(如 `NSMutableString` 赋值给 `NSString`)。 - 深拷贝可能带来性能开销,需权衡内存与独立性需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值