Copy

IOS/Objective-C 2015. 8. 18. 12:04

copy, mutableCopy

NSObject에는  리시버를 복사하는 copy라는 메서드가 있다. 단, 실제 복사 처리를 하는것은 copy가 아니라 copyWithZone:이라는 인스턴스 메서드이다. 인스턴스 객체에 copy메세지를 보내면 인수로 NULL을 지정해서 자기 자신의 copyWithZone을 호출해서 Default Zone에 새로운 인스턴스를 만들 수 있다.

이러한 원리로, 인스턴스가 복사되도록 하기 위해서는 copy 메소드가 아닌 copyWithZone: 메소드를 정의해야 한다. 만약 복사가 실패했을 경우 copy, copyWithZone 둘 다 nil을 리턴한다.

copyWithZone:은 NSCopying 프로토콜 내에서 선언되어 있으므로 이 프로토콜을 적용해서 구현한다.


*인스턴스 객체를 바이트 배열로 간주하고 통째로 복사해서 다른 객체를 리턴하는 함수가 제공 됨.

 - id NSCopyObject(id anObject, NSUInteger extraBytes, NSZone *zone)

   - 인수의 anObject가 원본 객체이고 extraBytes는 보통 0을 지정함, 인수 zone에 NULL을 지정하면 default zone이 사용됨.

   -  문제점 : 원본 객체의 인스턴스 객체들까지 copy가 되지 않는다.(객체 내용의 바이트 배열을 복사하기만 하므로..) 즉, 원본객체와 복사객체 모두 해당 인스턴스 객체를 강한 참조하게 된다, 또한 MRC를 사용할 경우 해당 인스턴스 객체에 retain count가 자동 증가되지 않기 때문에 copy 후 retain을 해줘야 함. -> 즉, 단순히 값을 복사하기만 하면 되는 인스턴스가 많을 경우 유용.


- 불변객체에서 가변객체 복사를 생성하려면 mutableCopy메서드가 위에 copy메서드와 대응되고,    mutablecopyWithZone:이 copyWithZone:과 대응된다. 동작 메커니즘은 똑같다.


얕은복사 vs 깊은
복사
: 얕은복사는 메모리 주소를 복사한다는 것이다. 즉, 똑같은 인스턴스를 두개의 포인터가 가리키고 있게 된다.
깊은 복사는 새로운 메모리 공간을 할당해서 인스턴스의 값을 복사한다는 것이다. 서로 다른 공간의 메모리가 생기고 두개의 포인터는 각각의 메모리 공간을 가리키게 된다.

: NSArray와 같은 파운데이션 프레임워크에 있는 모든 클래스는 얕은 복사를 지원한다. 즉, NSArray에 copy메세지를 보내도 array가 포함하고 있는 각 객체들에게 copy 메세지를 보내서 복사하는게 아니라 메모리 주소만 복사한다.
깊은 복사를 하기 위해서는 array계열 클래스는 'initWithArray:copyItems:' 메서드가 있고, 다른 컬렉션 클래스에도 비슷하게 'copyItems:' 으로 끝나는 메서드가 존재한다. 해당 메서드를 호출할 때 copyItems 인자에 'YES'를 넘기면 각 컬렉션들이 포함하고 있는 객체에 copy메세지를 보내 복사하게 된다. 단 각 객체가 <NSCopying> 프로토콜을 conform 하지 않으면 런타임 에러가 발생한다. 


'IOS > Objective-C' 카테고리의 다른 글

Property List  (0) 2015.08.20
Archive  (0) 2015.08.20
Zone  (0) 2015.08.18
클래스 클러스터  (0) 2015.08.12
BOOL  (0) 2015.08.12
Posted by 홍성곤
,