IOS ObjectiveC中的赋值与对象拷贝

在开发过程中我们经常会遇到对象拷贝的问题,下面我们分别讨论赋值操作、对象拷贝、以及浅拷贝(Shallow copy)与深拷贝(Deep copy)的区别与各自的实现方式。
一、不同对象的赋值操作
Objective-C中有两类对象,一类是结构体(或者基本数据类型也算),另一类是NSObject对象。
对于结构体,代码直接会操作其实体,因此赋值操作会创建一个源对象的副本(一个新的对象);而对于NSObject对象,必须使用指针来操作对象,所以其赋值操作相当于复制了指针,而非对象,也就是说赋值操作使得源指针和新指针都指向同一个NSObject对象。这样讲有些难以理解,请看下面的代码:
// main.m
#import <Foundation/Foundation.h>
@interface TestObject : NSObject
{
@public
int x;
int y;
}
@end
@implementation TestObject
@end
typedef struct TestStruct
{
int x;
int y;
}
TestStruct;
int main(int argc, const char * argv[])
{
@autoreleasepool {
TestStruct ts1 = {100, 50};
NSLog(@"ts1: %p, %d, %d", &ts1, ts1.x, ts1.y);
TestStruct ts2 = ts1;
NSLog(@"ts2: %p, %d, %d", &ts2, ts2.x, ts2.y);
TestObject* to1 = [[[TestObject alloc] init] autorelease];
NSLog(@"to1: %p, %d, %d", to1, to1->x, to1->y);
TestObject* to2 = to1;
NSLog(@"to2: %p, %d, %d", to2, to2->x, to2->y);
}
return 0;
}
程序的运行结果如下:
ts1: 0x7fff63463898, 100, 50 ts2: 0x7fff63463890, 100, 50 to1: 0x7fc342d00370, 0, 0 to2: 0x7fc342d00370, 0, 0
程序代码首先定义了一个类TestObject(继承自NSObject),然后又定义了一个结构体TestStruct。这两者都包含两个整型的成员变量x和y。然后在main函数中,程序首先为TestStruct结构体ts1分配内存空间,并为其成员变量赋初值,x为100,y为50。然后通过NSLog函数打印出该结构体的地址和成员变量的值,即输出的第一行内容。接着,程序执行了赋值语句,将ts1赋值给另一个TestStruct结构体对象ts2,这条语句会为ts2分配另一块内存,然后把ts1的每个成员变量的值复制过来。第二行输出也可以看出来,地址不一样了,所以如果修改ts1的成员变量的值,是不会影响ts2的。
接着再来看TestObject。程序接着使用alloc静态方法分配了一块新的内存空间,然后通过init实例方法进行初始化(所有成员变量的值为0),最后将该内存空间的首地址返回。to1的实质就是一个指针,指向创建的TestObject对象。接着,程序将to1赋值给to2。to2也是一个指向TestObject对象的指针,其值与to1一样,即两者都指向同一个对象。所以在这种情况下,对to1的修改会同时影响to2。
二、对象拷贝
Foundation框架的NSObject类提供了两个方法,分别是copy和mutableCopy方法,用于对NSObject对象进行拷贝操作。copy方法会调用NSCopying协议的copyWithZone:方法,而mutableCopy会调用 NSMutableCopying协议的mutableCopyWithZone:方法。将上面的代码修改如下:
#import <Foundation/Foundation.h>
@interface TestObject : NSObject
{
@public
int x;
int y;
}
@end
@implementation TestObject
- (NSString*)description
{
return [NSString stringWithFormat:@"%@: %p, x: %d, y: %d", [self class], self, x, y];
}
@end
typedef struct TestStruct
{
int x;
int y;
}
TestStruct;
int main(int argc, const char * argv[])
{
@autoreleasepool
{
TestObject* to1 = [[[TestObject alloc] init] autorelease];
to1->x = 100; to1->y = 50;
TestObject* to2 = [[[TestObject alloc] init] autorelease];
to2->x = 200; to2->y = 400;
TestObject* to3 = [[[TestObject alloc] init] autorelease];
to3->x = 300; to3->y = 500;
//创建包含to1, to2, to3的数组array1
NSArray* array1 = [NSArray arrayWithObjects:to1, to2, to3, nil];
NSLog(@"array1: %p, \n%@", array1, array1);
//array2是array1调用copy的结果
NSArray* array2 = [array1 copy];
NSLog(@"array2: %p, \n%@", array2, array2);
[array2 release];
//mutableArray2是array1调用mutableCopy的结果
NSMutableArray* mutableArray2 = [array1 mutableCopy];
NSLog(@"mutableArray2: %@, %p, \n%@", [mutableArray2 class], mutableArray2, mutableArray2);
[mutableArray2 removeLastObject];
NSLog(@"After remove last object of mutableArray2");
NSLog(@"array1: %p, \n%@", array1, array1);
NSLog(@"array2: %p, \n%@", array2, array2);
NSLog(@"mutableArray2: %p, \n%@", mutableArray2, mutableArray2);
//mutableArray3是mutableArray2调用mutableCopy的结果
NSMutableArray* mutableArray3 = [mutableArray2 mutableCopy];
NSLog(@"mutableArray3: %p, \n%@", mutableArray3, mutableArray3);
[mutableArray2 release];
//array4是mutableArray3调用copy的结果
NSArray* array4 = [mutableArray3 copy];
NSLog(@"array4: %@, %p, \n%@", [array4 class], array4, array4);
[mutableArray3 release];
[array4 release];
}
return 0;
}
程序的运行结果如下:
2012-03-22 19:20:49.548 ObjectCopy[18042:403] array1: 0x7f9071414820, ( "TestObject: 0x7f90714141b0, x: 100, y: 50", "TestObject: 0x7f90714141c0, x: 200, y: 400", "TestObject: 0x7f9071414230, x: 300, y: 500" ) 2012-03-22 19:20:49.550 ObjectCopy[18042:403] array2: 0x7f9071414820, ( "TestObject: 0x7f90714141b0, x: 100, y: 50", "TestObject: 0x7f90714141c0, x: 200, y: 400", "TestObject: 0x7f9071414230, x: 300, y: 500" ) 2012-03-22 19:20:49.551 ObjectCopy[18042:403] mutableArray2: __NSArrayM, 0x7f9072800000, ( "TestObject: 0x7f90714141b0, x: 100, y: 50", "TestObject: 0x7f90714141c0, x: 200, y: 400", "TestObject: 0x7f9071414230, x: 300, y: 500" ) 2012-03-22 19:20:49.552 ObjectCopy[18042:403] After remove last object of mutableArray2 2012-03-22 19:20:49.552 ObjectCopy[18042:403] array1: 0x7f9071414820, ( "TestObject: 0x7f90714141b0, x: 100, y: 50", "TestObject: 0x7f90714141c0, x: 200, y: 400", "TestObject: 0x7f9071414230, x: 300, y: 500" ) 2012-03-22 19:20:49.553 ObjectCopy[18042:403] array2: 0x7f9071414820, ( "TestObject: 0x7f90714141b0, x: 100, y: 50", "TestObject: 0x7f90714141c0, x: 200, y: 400", "TestObject: 0x7f9071414230, x: 300, y: 500" ) 2012-03-22 19:20:49.553 ObjectCopy[18042:403] mutableArray2: 0x7f9072800000, ( "TestObject: 0x7f90714141b0, x: 100, y: 50", "TestObject: 0x7f90714141c0, x: 200, y: 400" ) 2012-03-22 19:20:49.557 ObjectCopy[18042:403] mutableArray3: 0x7f90729000d0, ( "TestObject: 0x7f90714141b0, x: 100, y: 50", "TestObject: 0x7f90714141c0, x: 200, y: 400" ) 2012-03-22 19:20:49.558 ObjectCopy[18042:403] array4: __NSArrayI, 0x7f9071416e70, ( "TestObject: 0x7f90714141b0, x: 100, y: 50", "TestObject: 0x7f90714141c0, x: 200, y: 400" )
程序的运行结果有几点值得注意,首先是array1与array2的地址相同,因为NSArray对象在创建之后是不可以修改的。其次,NSArray的mutableCopy方法会返回一个NSMutableArray对象。第三,对于NSArray或者NSMutableArray来说,mutableCopy方法会创建新的可变数组对象,但其每个数组成员的值仅仅是原数组的一个指针赋值,这就是浅拷贝。而与之相对的则是深拷贝,即复制数组时不是复制数组每个元素的引用,而是创建一个与之相同的新对象。
第四,在NSArray对象上调用mutableCopy方法返回一个NSMutableArray对象,而在NSMutableArray对象上调用copy方法则返回一个NSArray对象,而不是NSMutableArray对象。
当然,以上讨论的是Foundation框架中的NSArray与NSMutableArray类,如果想要实现对自己创建的类的对象进行拷贝,则需要让类实现NSCopying协议。
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
# IOS
# ObjectiveC中的赋值与对象拷贝
# 对象的深拷贝与浅拷贝
# 详解iOS的深浅拷贝
# 浅析iOS中的浅拷贝和深拷贝(copy和mutableCopy)
# 通过源码分析iOS中的深拷贝与浅拷贝
# 法会
# 与之
# 创建一个
# 的是
# 这就是
# 如有
# 则是
# 不可以
# 中有
# 而在
# 这条
# 希望能
# 再来
# 仅仅是
# 为其
# 几点
# 要让
# 可以看出
# 以其
# 也算
相关文章:
网站制作话术技巧,网站推广做的好怎么话术?
利用JavaScript实现拖拽改变元素大小
无锡制作网站公司有哪些,无锡优八网络科技有限公司介绍?
完全自定义免费建站平台:主题模板在线生成一站式服务
建站IDE高效指南:快速搭建+SEO优化+自适应模板全解析
学校免费自助建站系统:智能生成+拖拽设计+多端适配
盐城做公司网站,江苏电子版退休证办理流程?
如何在阿里云虚拟主机上快速搭建个人网站?
建站之星伪静态规则如何设置?
高端建站如何打造兼具美学与转化的品牌官网?
手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?
北京网站制作网页,网站升级改版需要多久?
如何通过商城免费建站系统源码自定义网站主题?
如何快速上传自定义模板至建站之星?
淘宝制作网站有哪些,淘宝网官网主页?
微网站制作教程,不会写代码,不会编程,怎么样建自己的网站?
智能起名网站制作软件有哪些,制作logo的软件?
模具网站制作流程,如何找模具客户?
如何在西部数码注册域名并快速搭建网站?
如何在阿里云完成域名注册与建站?
专业商城网站制作公司有哪些,pi商城官网是哪个?
香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化
无锡营销型网站制作公司,无锡网选车牌流程?
如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南
如何快速查询网址的建站时间与历史轨迹?
如何在IIS管理器中快速创建并配置网站?
如何快速选择适合个人网站的云服务器配置?
如何通过可视化优化提升建站效果?
如何在Windows 2008云服务器安全搭建网站?
如何在建站之星网店版论坛获取技术支持?
在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?
陕西网站制作公司有哪些,陕西凌云电器有限公司官网?
上海制作企业网站有哪些,上海有哪些网站可以让企业免费发布招聘信息?
如何快速搭建支持数据库操作的智能建站平台?
如何注册花生壳免费域名并搭建个人网站?
自助网站制作软件,个人如何自助建网站?
如何快速搭建虚拟主机网站?新手必看指南
台州网站建设制作公司,浙江手机无犯罪记录证明怎么开?
南京做网站制作公司,南京哈发网络有限公司,公司怎么样,做网页美工DIV+CSS待遇怎么样?
建站主机如何选?性能与价格怎样平衡?
网站app免费制作软件,能免费看各大网站视频的手机app?
如何在香港服务器上快速搭建免备案网站?
南平网站制作公司,2025年南平市事业单位报名时间?
兔展官网 在线制作,怎样制作微信请帖?
rsync同步时出现rsync: failed to set times on “xxxx”: Operation not permitted
如何规划企业建站流程的关键步骤?
建站之星×万网:智能建站系统+自助建站平台一键生成
国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?
如何快速生成凡客建站的专业级图册?
如何通过FTP空间快速搭建安全高效网站?
*请认真填写需求信息,我们会在24小时内与您取得联系。