Objective-Cでシンプルにシリアライズするカテゴリを作りました。
まずはじめに断っておきます。
これは、めちゃくちゃ単純なカテゴリです。
しかしNSObjectのサブクラスであれば、どんなオブジェクトでも自身を簡単に保存できちゃうので、結構使っています。
クラス名をディレクトリのパスに変換して、クラス固有のパスを生成し、それとキーを組み合わせたファイルパスに保存する仕組みになっているので同じクラスのインスタンスかつ同じキーを使うことで、同じデータを保存(書き出し)&復元(読み込み)するカテゴリです。
ソースコードはこちらです。
JAGSerialize
使い方
例えば、NSObjectのサブクラスCustomObjectClassがあるとします。
そのオブジェクトが使うデータは、NSArrayのインスタンス変数で保持しているとします。
@interface CustomObjectClass ()
@property (nonatomic,readwrite)NSArray *dataArray;
@end
それを保存する場合は、saveWithData:forKey
メソッドでそのインスタンス変数と固有のキーを指定してください。
一応バックグラウンド用のsaveWithData:forKey:completionBlock:
メソッドもあります。
- (void)_save{
[self saveWithData:_dataArray forKey:@"data"];
}
- (void)_saveBackground{
[self saveWithData:_dataArray forKey:@"data" completionBlock:^(BOOL success) {
if () {
NSLog(@"Success");
} else {
NSLog(@"Error");
}
}];
}
読み出すときは、loadDataForKey
メソッドで読み出します。
こちらもバックグラウンドで処理するloadDataForKey:completionBlock:
メソッドがあります。
- (void)_load{
_dataArray = [self loadDataForKey:@"data"];
if (_dataArray) {
} else {
_dataArray = [NSArray new];
}
}
- (void)_loadBackground{
_dataArray = [self loadDataForKey:@"" completionBlock:^(id dataObject) {
if (dataObject) {
_dataArray = dataObject;
} else {
_dataArray = [NSArray new];
}
}];
}
このような感じで簡単に使えるカテゴリです。
仕組み/実装
Documentsディレクトリにクラス名のディレクトリを作って、そこにクラス名+固有のキーをファイル名としたデータをNSKeyedArchiver
のarchiveRootObject:toFile:
メソッドで保存するようにしています。
一応隠しファイルとしています。
- (BOOL)saveWithData:(id<NSCoding>)data forKey:(NSString *)key{
NSString *fileName = [NSString stringWithFormat:@".%@-%@.dat",NSStringFromClass([self class])],key];
NSString *archiveFilePath = [self _archiveFilePathWithDirectoryNameInDocumentsDirectory:[[NSString alloc]initWithFormat:@".%@",NSStringFromClass([self class])]
fileName:fileName];
if ( [NSKeyedArchiver archiveRootObject:data toFile:archiveFilePath] ) {
return YES;
} else {
return NO;
}
}
// Documentsディレクトリの中にディレクトリとファイル名を繋げたファイルパスを返す。
// ディレクトリがなければ新規作成する。
- (NSString *)_archiveFilePathWithDirectoryNameInDocumentsDirectory:(NSString *)dirName fileName:(NSString *)fileName{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirPath = [paths objectAtIndex:0];
NSString *archiveDirPath = [documentsDirPath stringByAppendingPathComponent:dirName];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
if (![fileManager fileExistsAtPath:archiveDirPath]) {
if ( [fileManager createDirectoryAtPath:archiveDirPath
withIntermediateDirectories:YES
attributes:nil
error:&error] ) {
if (error) {
NSLog(@"Error");
}
}
}
NSString *archiveFilePath = [archiveDirPath stringByAppendingPathComponent:fileName];
return archiveFilePath;
}
読み出すときは、逆にNSKeyedUnarchiver
のunarchiveObjectWithFile
メソッドで読みだしています。
ぼくは、毎回考えるのが面倒なのでクラス名のディレクトリを生成していますが、固有のディレクトリ名にしても良いと思います。
Githubにアップしましたので、自由に使ってください。
CocoaPodsをお使いの場合は、
pod 'JAGSerialize', :git => 'https://github.com/ryuiwasaki/JAGSerialize.git'
とPodsfileに書き加えてください。