아카이빙(Archiving)
: 객체를 저장 / 복원 하는 기능.
1) XML 형태로 저장 / 복원
XML 형태로 plist (property list)를 저장.
plist 작성 방법은 NSArray 배열 객체를 만들고 객체들을 Array에 담은 후에 NSArray에서 제공하는 writeToFile 메소드로 파일로 보내면 됨.
★★특정 클래스만 가능 (커스텀 클래스를 저장하려하면 에러)
[제한된 클래스 종류]
NSStirng
NSArray
NSDictionary
NSDate
NSData
NSNumber
는 클래스 자체에서 제공하는 I/O기능으로 저장하면 됨.
ex) 실행파일(main.m)
#import <Foundation/Foundation.h>
#import "Cat.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSDictionary *dic= @{@"my_key":@"my_value"};
NSString *str = @"My String !!";
NSDate *date = [NSDate date];
NSNumber *num = @1234;
NSArray *my_array = @[dic,str,date,num];
NSString *filePath = @"/Users/night-ohl/Desktop/my_objs";
BOOL ret = [my_array writeToFile:filePath atomically:YES];
NSLog(@"Result : %d", ret);
}
return 0;
}
==> 결과 :
2019-02-16 16:00:16.503221+0900 Study[5717:320667] Result : 1
Program ended with exit code: 0
객체가 xml 형식으로 잘 저장된 것을 확인할 수 있음.
불러오기 과정은 생략.
2) 커스텀 클래스 인코딩/디코딩
Custom Class는 직렬화(Serialize) 방법으로 저장.
클래스를 직렬화 하려면 NSCoding 프로토콜에 선언된 인코딩/디코딩 메소드를 작성하여 사용.
[NSCoding 프로토콜 선언부 구성]
@protocol NSCoding
-(void)encodeWithCoder:(NSCoder *)aCoder; //인코딩 메소드
-(id)initWithCoder:(NSCoder *)aDecoder; //디코딩 메소드
@end
NSCoding 프로토콜의 인코딩/디코딩 메소드의 구현은 인자로 받는 NSCoder 클래스의 메소드들을 이용하여 구현.
부모 클래스도 직렬화 하려면?
인코딩 메소드 구현 상단에 [super encodeWithCoder:aCoder]; 작성.
디코딩 메소드 구현 상단에 self = [super initWithCoder:aDecoder]; 작성.
(super 에서도 NSCoding 프로토콜의 인코딩/디코딩 메소드를 호출한다 라는 의미)
[NSCoder 클래스 구성]
주요 메소드만 살펴보면
(인코딩)
-(void)encodeInt:(int)into forKey(NSString *)key; //정수를 인코딩
-(void)encodeObject:(id)obj forKey:(NSString *)key; //객체를 인코딩
(디코딩)
-(int)decodeIntForKey:(NSStirng *)key;
-(id)decodeObjectForKey:(NSString *)key;
위 메소드를 이용하여 클래스 멤버 변수/프로퍼티 를 하나하나 '키-밸류' 방식으로 인코딩/디코딩
[지금까지의 과정 정리]
1) 인코딩 디코딩이 필요한 클래스에서 NSCoding 프로토콜을 채택.
2) NSCoding 프로토콜은 NSCoder 클래스를 인자로 받음.
3) NSCoding 프로토콜의 인코딩/디코딩 메소드를 -> NSCoder 클래스의 메소드들을 이용하여 구현.
4) NSCoding 프로토콜의 인코딩(encodeWithCoder) / 디코딩(initWithCoder) 메소드 준비 완료.
그렇다면 인코딩/디코딩 메소드는 언제 호출할까?
여기서 주의할 점은 우리가 정의한 인코딩/디코딩 메소드를 직접 사용하지 않고, '아카이브'를 통함.
다시말해, 지금까지 작성한 메소드는 인코딩/디코딩을 위한 준비만 했을 뿐이고, 실제 동작은 '아카이브'를 통함.
[아카이버]
아카이버(Archiver) 클래스가 준비된 인코딩/디코딩 메소드를 이용하여 객체들를 파일로 저장하거나 복원함.
iOS용 파운데이션에서 사용할 수 있는 아카이버 '클래스' 2가지
NSKeyedArchiver : 클래스에 있는 내용을 (파일 혹은 NSData형태)로 저장.
NSKeyedUnarchiver : (파일 혹은 NSData) 형태로 저장된 것을 객체 형태로 복원.
<NSCoding> 프로토콜을 채택하여 구현한 인코딩/디코딩 메소드가 아카이브 메소드를 통해 자동으로 동작함.
NSKeydArchiver 클래스
+(BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path; //객체를 파일로 저장.
NSKeyedUnarchiver 클래스
+(id)unarchiveObjectWithFile:(NSString *);
등등..
ex)
[Rectangle 클래스 선언부 Rectangle.h]
#import <Foundation/Foundation.h>
@interface Rectangle : NSObject <NSCoding> //NSCoding 프로토콜을 채택.
@property int width;
@property int height;
@end
[Rectangle 클래스 구현부 Rectangle.m]
#import "Rectangle.h"
@implementation Rectangle
-(void)encodeWithCoder:(NSCoder *)aCoder{ //NSCoding 프로토콜의 인코딩 메소드 작성
[aCoder encodeInt:_width forKey:@"WIDTH"];
[aCoder encodeInt:_height forKey:@"HEIGHT"];
}
//저장된 객체를 복원
-(id)initWithCoder:(NSCoder *)aDecoder{ //NSCoding 프로토콜의 디코딩 메소드 작성
self = [super init];
if(self){
//디코딩 후 멤버변수를 초기화하는 과정
_width = [aDecoder decodeIntForKey:@"WIDTH"];
_height = [aDecoder decodeIntForKey:@"HEIGHT"];
}
return self;
}
-(NSString *)description{
return [NSString stringWithFormat:@"사각형 - 가로,세로 (%d, %d)\n", _width, _height];
}
@end
[실행 파일 main.m]
#import <Foundation/Foundation.h>
#import "Rectangle.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Rectangle *rec = [[Rectangle alloc] init];
rec.width = 10;
rec.height = 20;
NSLog(@"Rec1 : %@",rec);
NSString *filePath = @"/Users/night-ohl/Desktop/archiving";
BOOL ret = [NSKeyedArchiver archiveRootObject:rec toFile:filePath];
NSLog(@"Ret: %d",ret);
Rectangle *rec2 = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"Rec2 : %@",rec2);
}
return 0;
}
==> 결과 :
아카이버 호출 후 archiving 객체가 인코딩 되어 파일로 저장된 모습.
2019-02-18 11:29:01.833929+0900 Study[8084:1182913] Rec1 : 사각형 - 가로,세로 (10, 20) 객체생성
2019-02-18 11:29:01.835339+0900 Study[8084:1182913] Ret: 1 객체를 인코딩하여 파일로 저장
2019-02-18 11:29:01.835881+0900 Study[8084:1182913] Rec2 : 사각형 - 가로,세로 (10, 20) 파일로부터 디코딩하여 객체 복원
Program ended with exit code: 0
바이너리 데이터인 NSData 객체를 저장/복원 하는 내용은 다음 글에서 정리함.
'Objective-C 기초' 카테고리의 다른 글
블록 (Block) (0) | 2019.02.18 |
---|---|
NSData 다루기 (바이너리 데이터 저장/복원) (0) | 2019.02.18 |
프로토콜 (Protocol) (0) | 2019.02.15 |
클래스 내부 구성요소 숨기기 (0) | 2019.02.15 |
카테고리 Category (0) | 2019.02.15 |