1205 字
6 分钟
【iOS】对象复制与属性关键字
目录
二、NSCopying和NSmutableCopying协议
对象复制
一、copy与mutableCopy方法
copy方法用于复制对象的副本,复制下来的该副本是不可修改的,哪怕是调用NSMutableString的copy方法也不可修改。
而mutableCopy方法复制下来的副本是可修改的,即使被复制的对象原本是不可修改的。例如调用mutableCopy方法复制NSString的,返回的是一个NSMutableString对象。
以下用代码演示copy和mutableCopy方法的功能:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) { @autoreleasepool { //copy与mutableCopy NSMutableString *book = [NSMutableString stringWithString: @"疯狂iOS讲义"];
NSMutableString *bookCopy = [book mutableCopy]
[bookCopy replaceCharactersInRange: NSMakeRange(2, 3) withString: @"Android"];//复制后的bookCopy副本是可以修改的,这里做个修改,对原字符串的值也没有影响
NSLog(@"book的值为:%@",book);//原值
NSLog(@"bookCopy的值为:%@",bookCopy);//副本修改后的值
NSString *str = @"fkit";//定义一个str字符串 NSMutableString *strCopy = [str mutableCopy];//用mutableCopy给str复制一个副本
[strCopy appendString:@".org"];//向可变字符串后面追加字符串 NSLog(@"%@",strCopy);
NSMutableString *bookCopy2 = [book copy];//用copy方法复制一个book的副本(这个副本不可变) [bookCopy2 appendString:@"aa"];//这里会报错,因为copy创建的副本不可变,修改了就崩了
} return 0;}### 二、NSCopying和NSmutableCopying协议
当我们想将自定义类用上一节的两个方法复制副本时,我们可能会直接创建完对象后用”类名* 对象2 = [对象1 copy];“这样的格式来复制副本,但实际上直接这样复制是不对的,会报错说找不到copyWithZone:方法,mutableCopy也是一样。因此我们可以看出,自定义类是不能直接调用这两个方法来复制自身的。
这是为什么呢?是因为当程序调用copy/mutableCopy方法复制时,程序底层需要调用copyWithZone:/mutableCopyWithZone:方法来完成复制的工作,并返回这两个方法的值。因此为了保证可以复制,需要在自定义类的接口部分声明NSCopying/NSMutableCopying协议,然后再类的实现部分增加copyWithZone:/mutableCopyWithZone:方法,因此,对自定义对象的复制应该如下所示:
接下来,我们以一个自定义的Person类为例,支持copy和mutablecopy:
```objective-c#import <Foundation/Foundation.h>
@interface Person : NSObject <NSCopying, NSMutableCopying>@property (nonatomic, copy) NSString *name;@property (nonatomic, assign) NSInteger age;@end
@implementation Person
// 实现 copy(返回不可变副本)- (id)copyWithZone:(NSZone *)zone { Person *copy = [[[self class] allocWithZone:zone] init]; copy.name = [self.name copy]; copy.age = self.age; return copy;}
// 实现 mutableCopy(返回可变副本)- (id)mutableCopyWithZone:(NSZone *)zone { Person *copy = [[[self class] allocWithZone:zone] init]; copy.name = [self.name mutableCopy]; // 注意生成可变副本 copy.age = self.age; return copy;}
@endint main(int argc, const char * argv[]) { @autoreleasepool { Person *p1 = [[Person alloc] init]; p1.name = @"Tom"; p1.age = 18;
Person *p2 = [p1 copy]; // 调用 copyWithZone Person *p3 = [p1 mutableCopy]; // 调用 mutableCopyWithZone
NSLog(@"原始:%@ %ld", p1.name, p1.age); NSLog(@"copy:%@ %ld", p2.name, p2.age); NSLog(@"mutableCopy:%@ %ld", p3.name, p3.age); } return 0;}### 三、深复制与浅复制
深复制和浅复制是面向对象编程中非常重要的概念。
浅复制:仅复制对象的指针地址,多个变量共享同一个对象。
深复制: 不仅复制指针,还会复制整个对象内容,使得原对象和副本完全独立。
举个例子:
```objective-cNSMutableString *str1 = [NSMutableString stringWithString:@"Hello"];NSMutableString *str2 = str1; // 浅复制(赋值)// 修改 str1,str2 也变了[str1 appendString:@" World"];因此总而言之,浅拷贝就是创建一个副本,对内存地址的复制。深拷贝就是创建一个副本,对内容完全复制。原始对象与副本对象内存地址不同。
按照类型说明:
非容器类对象的深拷贝与浅拷贝
不可变字符串
int main(int argc, const char * argv[]) { @autoreleasepool { NSString* str1 = @"dddddd"; NSString* str2 = [str1 copy]; NSString* str3 = [str1 mutableCopy]; NSMutableString* str4 = [str1 copy]; NSMutableString* str5 = [str1 mutableCopy]; NSLog(@"str1:%p", str1); NSLog(@"str2:%p", str2); NSLog(@"str3:%p", str3); NSLog(@"str4:%p", str4); NSLog(@"str5:%p", str5); } return 0;}
得出结论: 不可变字符串,只要是copy就是浅拷贝,mutableCopy是深拷贝。tips:我们用NSString stringWithstring 方式创建的是一个常量区字符串。

原文发布于 CSDN:【iOS】对象复制与属性关键字