当前位置: 移动技术网 > IT编程>移动开发>IOS > IOS ObjectiveC中的赋值与对象拷贝

IOS ObjectiveC中的赋值与对象拷贝

2019年07月24日  | 移动技术网IT编程  | 我要评论

国家公务员考试历年真题,7766小游戏,鬼异杂谈之养尸人

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 uicollectionview实现横向滚动

    现在使用卡片效果的app很多,之前公司让实现一种卡片效果,就写了一篇关于实现卡片的文章。文章最后附有demo实现上我选择了使用uicollectionview ... [阅读全文]
  • iOS UICollectionView实现横向滑动

    本文实例为大家分享了ios uicollectionview实现横向滑动的具体代码,供大家参考,具体内容如下uicollectionview的横向滚动,目前我使... [阅读全文]
  • iOS13适配深色模式(Dark Mode)的实现

    iOS13适配深色模式(Dark Mode)的实现

    好像大概也许是一年前, mac os系统发布了深色模式外观, 看着挺刺激, 时至今日用着也还挺爽的终于, 随着iphone11等新手机的发售, ios 13系统... [阅读全文]
  • ios 使用xcode11 新建项目工程的步骤详解

    ios 使用xcode11 新建项目工程的步骤详解

    xcode11新建项目工程,新增了scenedelegate这个类,转而将原appdelegate负责的对ui生命周期的处理担子接了过来。故此可以理解为:ios... [阅读全文]
  • iOS实现转盘效果

    本文实例为大家分享了ios实现转盘效果的具体代码,供大家参考,具体内容如下demo下载地址: ios转盘效果功能:实现了常用的ios转盘效果,轮盘抽奖效果的实现... [阅读全文]
  • iOS开发实现转盘功能

    本文实例为大家分享了ios实现转盘功能的具体代码,供大家参考,具体内容如下今天给同学们讲解一下一个转盘选号的功能,直接上代码直接看viewcontroller#... [阅读全文]
  • iOS实现轮盘动态效果

    本文实例为大家分享了ios实现轮盘动态效果的具体代码,供大家参考,具体内容如下一个常用的绘图,主要用来打分之类的动画,效果如下。主要是ios的绘图和动画,本来想... [阅读全文]
  • iOS实现九宫格连线手势解锁

    本文实例为大家分享了ios实现九宫格连线手势解锁的具体代码,供大家参考,具体内容如下demo下载地址:效果图:核心代码://// clockview.m// 手... [阅读全文]
  • iOS实现卡片堆叠效果

    本文实例为大家分享了ios实现卡片堆叠效果的具体代码,供大家参考,具体内容如下如图,这就是最终效果。去年安卓5.0发布的时候,当我看到安卓全新的material... [阅读全文]
  • iOS利用余弦函数实现卡片浏览工具

    iOS利用余弦函数实现卡片浏览工具

    本文实例为大家分享了ios利用余弦函数实现卡片浏览工具的具体代码,供大家参考,具体内容如下一、实现效果通过拖拽屏幕实现卡片移动,左右两侧的卡片随着拖动变小,中间... [阅读全文]
验证码:
移动技术网