Farlanki

‘Swift中的浅复制和深复制’

字数统计: 907阅读时长: 4 min
2015/11/03 Share

浅复制和深复制

浅复制

浅复制是指在复制的时候,对象里的值类型被复制一份,而引用类型没有被复制,指向原来的对象.

深复制

深复制是指在复制的时候,对象里的值类型被复制一份,而引用类型也被复制一份.

swift中的浅复制和深复制的情况

在swift中,一个对象直接用等号赋值给另一个对象,则建立了两个指向同一个实例的引用.这种情况既不是浅复制也不是深复制.swift中的结构体,数组是浅复制的.(当然,也可以自己实现一个深复制的方法).

要建立复制,要实现NSCopying协议和实现其中的copyWithZone:方法

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
class Location{
var name:String
var address: String

init(name:String , address :String){
self.name = name;
self.address = address;
}
}

class Appointment : NSObject , NSCopying{
var name: String
var place: Location

init(name : String , place : Location){
self.name = name;
self.place = place;
}

func copyWithZone(zone : NSZone) -> AnyObject{
return Appointment(name:self.name , place : self.place);
}

func printDetails(label:String){
print("\(label) with \(name) at \(place.name)")
}
}

var beerMeeting = Appointment(name: "Bob", place: Location(name: "Joe's bar", address: "123 Main street"))

var workMeeting = beerMeeting.copy() as! Appointment
workMeeting.name = "Alice"
workMeeting.place.name = "Conference"
workMeeting.place.address = "Company"

beerMeeting.printDetails("Social")
workMeeting.printDetails("Work")

Social with Bob at Conference

Work with Alice at Conference

以上是浅复制的情况

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
class Location : NSObject , NSCopying{
var name:String
var address: String

init(name:String , address :String){
self.name = name;
self.address = address;
}

func copyWithZone(zone: NSZone) -> AnyObject {
return Location(name : self.name , address : self.address)//edited
}
}

class Appointment : NSObject , NSCopying{
var name: String
var place: Location

init(name : String , place : Location){
self.name = name;
self.place = place;
}

func copyWithZone(zone : NSZone) -> AnyObject{
return Appointment(name:self.name , place : self.place.copy() as! Location);//edited
}

func printDetails(label:String){
print("\(label) with \(name) at \(place.name)")
}
}

var beerMeeting = Appointment(name: "Bob", place: Location(name: "Joe's bar", address: "123 Main street"))

var workMeeting = beerMeeting.copy() as! Appointment
workMeeting.name = "Alice"
workMeeting.place.name = "Conference"
workMeeting.place.address = "Company"

beerMeeting.printDetails("Social")
workMeeting.printDetails("Work")

Social with Bob at Joe's bar

Work with Alice at Conference

以上是深复制的情况

NSArray 和 NSMutableArray 的情况

和内建的swift数组不同, NSArrayNSMutablearray在使用copy:方法或者mutablecopy:方法时才会采用浅复制,如果使用赋值符号的话是指向同一个实例.
如果在创建数组时使用@NSCopying关键字,就可以让赋值符号运算的复制从复制引用变成浅复制.
@NSCopying var data : NSArray

@NSCopying有其的限制:在NSMutableArray前加上这个关键字会导致数据类型变成NSArray,即使定义为NSMutableArray.

实现copy还是copyWithZone?:

在实现自己的类的时候,如果需要用到复制的特性,需要将把类实现NSCopying协议,实现copyWithZone:方法.拥有copy关键字的属性会在setter中调用copy方法,或者我们会在其他地方手动调用copy方法.copy方法的系统默认实现是调用copyWithZone:方法.所以如果自己的类没有实现copyWithZone:方法,但是类的copy方法被调用了,并且copy方法没有没重载(重载copy方法是不建议的),那么就会提示找不到copyWithZone:方法.所以,当使用到复制的特性的时候,自己的类需要先实现copyWithZone:方法.NSObject默认实现copy方法,但是却没有默认实现copyWithZone:方法,所以当我们调用系统的一些类的copy方法的时候,也会出错.例如

1
2
3
UIView * a = [[UIView alloc]init];
UIView *b = [a copy];
//Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView copyWithZone:]: unrecognized selector sent to instance 0x7f8239797f70'

参考:http://stackoverflow.com/questions/9280328/override-copy-or-copywithzone-or-both

@NSCopying

在引用类型前加上这个关键字可以在赋值号复制时把引用复制转变为浅复制

CATALOG
  1. 1. 浅复制和深复制
    1. 1.1. 浅复制
    2. 1.2. 深复制
    3. 1.3. swift中的浅复制和深复制的情况
  2. 2. NSArray 和 NSMutableArray 的情况
  3. 3. 实现copy还是copyWithZone?:
  4. 4. @NSCopying