[iPhone Dev] NSDictionary, NSArray 등의 저장에 대해
Mar 29
iphone apple, ios, iPad, iphone, NSArray, NSDictionary, NSPropertyListSerialization, 아이폰 No Comments
NSUserDefaults를 이용해서 NSString 기반으로 앱의 데이터를 저장하는 것은 손쉽지만, NSDictionary나 NSArry 등의 데이터를 저장하기는 불편할 것입니다.
NSPropertyListSerialization을 이용하는 방법을 주로 사용했었는데요, NSDictionary의 writeToFile:automatically과 dictionaryWithContentsOfFile: 을 이용해서 좀 더 직관적으로 하는 것도 좋을 것 같아서 포스팅 해봅니다.
[1] NSDictionary의 writeToFile:automatically과 dictionaryWithContentsOfFile: 이용
저장할 때는 writeToFile:automatically을 불러올 때는 dictionaryWithContentsOfFile: 을 이용하면 될 것입니다.
그리고 NSString의 stringByExpandingTildeInPath을 이용해서 Documents의 path도 쫌 더직관적으로 얻어 오면 다음과 같은 코드가 만들어질 것입니다.
[저장하기]
-(void)saveDic:(NSMutableDictionary*)aDic ForKey:(NSString*)aKey {
if( aDic == nil || aKey == nil ) {
return;
}
NSString* dataPath = [[NSString stringWithFormat:@"~/Documents/%@", aKey] stringByExpandingTildeInPath];
[aDic writeToFile:dataPath atomically:YES];
}
[불러오기]
-(NSMutableDictionary*)loadDicForKey:(NSString*)aKey {
if( aKey == nil ) {
return nil;
}
NSString* dataPath = [[NSString stringWithFormat:@"~/Documents/%@", aKey] stringByExpandingTildeInPath];
return [NSMutableDictionary dictionaryWithContentsOfFile:dataPath];
}
[사용 예]
NSPropertyListSerialization 의 사용에도 마찬가지지만, (실수에 의한) memory leak을 막기 위해서 데이터를 가지고 있는 object는 property로 처리하는 것이 좋은 것 같습니다.
// dictionaryWithContentsOfFile 이용
NSString* testKey = @"testKey";
self.dataDic = [self loadDicForKey:testKey];
if( self.dataDic ) {
NSLog(@"testKey (first): %@", self.dataDic);
}
[self.dataDic setObject:[NSArray arrayWithObjects:@"a", @"b", @"c", nil] forKey:@"abc"];
[self saveDic:self.dataDic ForKey:testKey];
self.dataDic = nil;
self.dataDic = [self loadDicForKey:testKey];
if( self.dataDic ) {
NSLog(@"testKey (second): %@", self.dataDic);
}
[2] NSPropertyListSerialization 이용
아래 코드에 주석으로 표기 했지만, propertyListFromData:mutabilityOption:format:error: 이나 dataFromPropertyList:format:error: 등은 곧 decprecate될 것이라고 하니 대체되는 method를 사용해야할 것입니다.
그리고 , [1]에서도 이야기 했지만, 데이터를 받는 객체는 property로 처리해줘야 memory leak을 깔끔하게 없앨 수 있겠죠.
[저장 및 불러오기]
-(NSMutableDictionary*)restoreDataForKey:(NSString*)aKey {
if( aKey == nil ) {
return nil;
}
NSString *finalPath = nil;
NSData *plistData;
NSError *error;
NSPropertyListFormat format;
// normal
finalPath = [self getFilePathForkey:aKey];
plistData = [NSData dataWithContentsOfFile:finalPath];
NSMutableDictionary* tempDic = nil;
if( plistData ) {
/*
// propertyListFromData will be deprecated soon.
dataDic = [NSPropertyListSerialization propertyListFromData:plistData
mutabilityOption:NSPropertyListMutableContainers
format:&format
errorDescription:&error];
*/
tempDic = [NSPropertyListSerialization propertyListWithData:plistData options:NSPropertyListMutableContainers format:&format error:&error];
}
if(tempDic == nil) {
tempDic = [[[NSMutableDictionary alloc] init] autorelease];
}
return tempDic;
}
-(void)storeData:(NSMutableDictionary*)aDic ForKey:(NSString*)aKey {
if( aDic == nil || aKey == nil ) {
return;
}
NSString *finalPath = nil;
NSData *xmlData;
NSError *error;
// normal
if(aDic != nil ) {
finalPath = [self getFilePathForkey:aKey];
/*
dataFromPropertyList will be deprecated soon.
xmlData = [NSPropertyListSerialization dataFromPropertyList:aDic
format:NSPropertyListXMLFormat_v1_0
errorDescription:&error];
*/
xmlData = [NSPropertyListSerialization dataWithPropertyList:aDic format:NSPropertyListXMLFormat_v1_0 options:0 error:&error];
if(xmlData) {
//NSLog(@"No error creating XML data.");
[xmlData writeToFile:finalPath atomically:YES];
}
else {
NSLog(@"%@", error);
[error release];
}
}
}
[사용 예]
// NSPropertyListSerialization 이용
testKey = @"testKey2";
self.dataDic2 = [self restoreDataForKey:testKey];
if( self.dataDic2 ) {
NSLog(@"testKey2 (first): %@", self.dataDic2);
}
[self.dataDic2 setObject:[NSArray arrayWithObjects:@"aa", @"bb", @"cc", nil] forKey:@"aabbcc"];
[self storeData:self.dataDic2 ForKey:testKey];
self.dataDic2 = nil;
self.dataDic2 = [self restoreDataForKey:testKey];
if( self.dataDic2 ) {
NSLog(@"testKey2 (scond): %@", self.dataDic2);
}
