全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

IOS ObjectiveC中的赋值与对象拷贝

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中的深拷贝与浅拷贝  # 法会  # 与之  # 创建一个  # 的是  # 这就是  # 如有  # 则是  # 不可以  # 中有  # 而在  # 这条  # 希望能  # 再来  # 仅仅是  # 为其  # 几点  # 要让  # 可以看出  # 以其  # 也算 


相关文章: 制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?  php条件判断怎么写_ifelse和switchcase的使用区别【对比】  seo网站制作优化,网站SEO优化步骤有哪些?  韩国网站服务器搭建指南:VPS选购、域名解析与DNS配置推荐  浅析上传头像示例及其注意事项  小型网站建站如何选择虚拟主机?  建站主机SSH密钥生成步骤及常见问题解答?  网站制作网站,深圳做网站哪家比较好?  成都网站制作价格表,现在成都广电的单独网络宽带有多少的,资费是什么情况呢?  网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?  Python lxml的etree和ElementTree有什么区别  整人网站在线制作软件,整蛊网站退不出去必须要打我是白痴才能出去?  如何通过商城免费建站系统源码自定义网站主题?  ,如何利用word制作宣传手册?  建站之星代理如何优化在线客服效率?  如何在Windows环境下新建FTP站点并设置权限?  如何用wdcp快速搭建高效网站?  网站制作中优化长尾关键字挖掘的技巧,建一个视频网站需要多少钱?  黑客如何通过漏洞一步步攻陷网站服务器?  北京专业网站制作设计师招聘,北京白云观官方网站?  c# 在ASP.NET Core中管理和取消后台任务  广德云建站网站建设方案与建站流程优化指南  网站制作公司排行榜,四大门户网站排名?  网站制作企业,网站的banner和导航栏是指什么?  C#如何序列化对象为XML XmlSerializer用法  代刷网站制作软件,别人代刷火车票靠谱吗?  儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?  成都品牌网站制作公司,成都营业执照年报网上怎么办理?  如何快速查询网址的建站时间与历史轨迹?  宝塔Windows建站如何避免显示默认IIS页面?  如何快速上传建站程序避免常见错误?  图片制作网站免费软件,有没有免费的网站或软件可以将图片批量转为A4大小的pdf?  图册素材网站设计制作软件,图册的导出方式有几种?  如何确保西部建站助手FTP传输的安全性?  大同网页,大同瑞慈医院官网?  如何通过VPS建站无需域名直接访问?  高性能网站服务器部署指南:稳定运行与安全配置优化方案  如何选择建站程序?包含哪些必备功能与类型?  如何在IIS7上新建站点并设置安全权限?  网站制作外包价格怎么算,招聘网站上写的“外包”是什么意思?  如何快速生成凡客建站的专业级图册?  ,巨量百应是干嘛的?  如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?  公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?  标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?  如何用花生壳三步快速搭建专属网站?  建站之星与建站宝盒如何选择最佳方案?  ,交易猫的商品怎么发布到网站上去?  JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)  怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。