Archive

IOS/Objective-C 2015. 8. 20. 19:48

객체 직렬화와 아카이브의 차이
: 코코아 프레임워크에서 직렬화(serialization)는 아카이브와 마찬가지로 객체 그래프를 따라 객체의 데이터 내용을 저장하는 방식이다. 다만, 아카이브와 달리 직렬화는 주로 문자열, 배열이나 사전 컬렉션에 담겨 있는 계층 구조와 참조하는 객체 데이터만 직접적으로 저장하며, 참조 관계에는 관심이 없고 데이터에만 관심이 있다. 예를 들어, 여러 곳에서 하나의 객체를 다중 참조하고 있으면 참조마다 동일한 내용을 각기 저장한다. 그러므로 deserialization 할 때에도, 동일한 객체를 다중 참조하는 것이 아니라 각기 다른 객체가 만들어진다는 것이다. 그리고 데이터에만 관심이 있기 때문에 해당 객체가 가변 객체였는지 불변 객체였는지 판단해서 복원할 수 없다.
객체 직렬화와 직접적으로 관련이 있는 클래스는 NSPropertyListSerialization이 있다. 이 클래스는 Foundation 객체 중에서 NSDictionary, NSArray, NSString, NSDate, NSData, NSNumber 타입으로 저장되어 있는 데이터 구조만 XML 기반 plist 파일로 직렬화 해서 저장한다. 
NSUserDefaults 클래스도 내부적으로 NSPropertyListSerialization을 사용해서 직렬화를 지원한다.

직렬화(Serialization)는 다중 참조 관계나 가변객체 여부등을 복원하지 못하고 저장할 수 있는 클래스 종류도 한정적이다. 이러한 제약 사항을 지원해야 하는 경우라면 <NSCopying> 프로토콜을 사용해야 한다. 

<NSCoding> 프로토콜

- 객체를 Archive, UnArchive하기 위해서는 NSKeyArchiver, NSKeyUnarchiver가 필요.
- Archive 대상이 되는 객체는 NSCoding 프로토콜을 따르고 있어야 함.
- NSCoding 프로토콜 : encodeWithCoder, initWithCoder:

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [super encodeWithCoder:aCoder];
    // 슈퍼 클래스가 NSCoder프로토콜을 따르지 않으면 불필요.
    [coder encodeObject:객체 forKey:키];
    [coder encodeDouble:실수 forKey:키];
    ....
}

먼저 슈퍼클래스가 NSCoding 프로토콜을 따르고 있으면 super의 encoderWithCoder를 호출해서 인코딩 후 자신을 인코딩함. 클래스가 독자적으로 가지고 있는 인스턴스 변수가 없고, 슈퍼클래스 에 encodeWithCoder:의 정의가 있는 경우라면 이 메소드 정의 자체가 필요 없음.
인코딩할때의 Key는 인스턴스 변수 각각에 다른 키를 지정해야 한다. 슈퍼 클래스에서 지정한 키를
서브 클래스에서 사용하면 안된다. 키는 같은 내부에서만 구별할 수 있으면 되기 때문에 다른 클래스
에서 같은키 사용 가능.
객체의 아카이브 메서드는 encodeObject:forKey:를 사용하는데, 이 함수는 첫 번째 인수인 객체에
대해 encodeWithCoder:를 호출해서 인코딩하므로, 이런 메소드는 재귀 호출한다. 객체 그래프에 순환 참조가 있는 경우, 같은 객체의 인코딩 요구가 여러 번 발생할 수 있지만 일단 아카이브한 객체를 중복해서 아키이브 하지 않음.

*encodeConditionalObject: (다른 곳에서 아카이브되어 있지 않으면 인코딩하지 않는 메서드)
- 아카이브 할때 인스턴스 변수 일부만 아카이브할 수가 있는데, 아카이브 하지 않은 인스턴스 변수를 객체 그래프의 순환참조가 있을경우 다른 곳에서 아카이브를 해버리면 복원하는 시점에 문제가 발생할 수 있다. 이때 사용하는 메서드.

- (id)initWithCoder:(NSCoder *)aCoder
{
    self = [super initWithCoder:aCoder];
    //슈퍼 클래스가 NSCoding 프로토콜을 따르지 않으면 [super init]만 하면 됨.
    
    변수 = [[coder decodeObjectForKey:키] retain];
    .....
    return self;
    
    // 인코딩도 디코딩과 같은 키를 지정하기만 하면, 디코딩하는 순서는 상관없고 복원하지 않는 변수가 있어도 상관 없음.
}

 


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

메소드의 동적 결합  (0) 2015.08.22
Property List  (0) 2015.08.20
Copy  (0) 2015.08.18
Zone  (0) 2015.08.18
클래스 클러스터  (0) 2015.08.12
Posted by 홍성곤
,