服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - IOS ObjectiveC中的赋值与对象拷贝

IOS ObjectiveC中的赋值与对象拷贝

2021-03-31 16:14偷笑黑桃K IOS

这篇文章主要介绍了IOS ObjectiveC中的赋值与对象拷贝的相关资料,希望通过本文能帮助到大家,让大家理解掌握这部分内容,需要的朋友可以参考下

IOS ObjectiveC中的赋值对象拷贝

在开发过程中我们经常会遇到对象拷贝的问题,下面我们分别讨论赋值操作、对象拷贝、以及浅拷贝(Shallow copy)与深拷贝(Deep copy)的区别与各自的实现方式。

一、不同对象的赋值操作

Objective-C中有两类对象,一类是结构体(或者基本数据类型也算),另一类是NSObject对象。

对于结构体,代码直接会操作其实体,因此赋值操作会创建一个源对象的副本(一个新的对象);而对于NSObject对象,必须使用指针来操作对象,所以其赋值操作相当于复制了指针,而非对象,也就是说赋值操作使得源指针和新指针都指向同一个NSObject对象。这样讲有些难以理解,请看下面的代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 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;
}

程序的运行结果如下:

?
1
2
3
4
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:方法。将上面的代码修改如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#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;
}

程序的运行结果如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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协议。

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

原文链接:http://blog.csdn.net/pucker/article/details/7384252

延伸 · 阅读

精彩推荐
  • IOSiOS中tableview 两级cell的展开与收回的示例代码

    iOS中tableview 两级cell的展开与收回的示例代码

    本篇文章主要介绍了iOS中tableview 两级cell的展开与收回的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    J_Kang3862021-04-22
  • IOSiOS通过逆向理解Block的内存模型

    iOS通过逆向理解Block的内存模型

    自从对 iOS 的逆向初窥门径后,我也经常通过它来分析一些比较大的应用,参考一下这些应用中某些功能的实现。这个探索的过程乐趣多多,不仅能满足自...

    Swiftyper12832021-03-03
  • IOSIOS开发之字典转字符串的实例详解

    IOS开发之字典转字符串的实例详解

    这篇文章主要介绍了IOS开发之字典转字符串的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的方法,需要的朋友可以参考下...

    苦练内功5832021-04-01
  • IOS解析iOS开发中的FirstResponder第一响应对象

    解析iOS开发中的FirstResponder第一响应对象

    这篇文章主要介绍了解析iOS开发中的FirstResponder第一响应对象,包括View的FirstResponder的释放问题,需要的朋友可以参考下...

    一片枫叶4662020-12-25
  • IOS关于iOS自适应cell行高的那些事儿

    关于iOS自适应cell行高的那些事儿

    这篇文章主要给大家介绍了关于iOS自适应cell行高的那些事儿,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    daisy6092021-05-17
  • IOSiOS 雷达效果实例详解

    iOS 雷达效果实例详解

    这篇文章主要介绍了iOS 雷达效果实例详解的相关资料,需要的朋友可以参考下...

    SimpleWorld11022021-01-28
  • IOSIOS 屏幕适配方案实现缩放window的示例代码

    IOS 屏幕适配方案实现缩放window的示例代码

    这篇文章主要介绍了IOS 屏幕适配方案实现缩放window的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    xiari5772021-06-01
  • IOSiOS布局渲染之UIView方法的调用时机详解

    iOS布局渲染之UIView方法的调用时机详解

    在你刚开始开发 iOS 应用时,最难避免或者是调试的就是和布局相关的问题,下面这篇文章主要给大家介绍了关于iOS布局渲染之UIView方法调用时机的相关资料...

    windtersharp7642021-05-04