web-dev-qa-db-ja.com

iOSの永続ストレージ戦略

ローカルファイルシステムにデータを保存するアプリを開発しています。保存されるデータは、ほとんどがNSStringとNSDateです。データはそれほど頻繁には保存されません。おそらく、通常の使用法で新しいデータが10回入力されるでしょう。もちろん、データは取得可能である必要があります(CRUD)

このデータをどのように保存すればよいですか?まず、これらのオブジェクトをモデル化する必要がありますか?そうでない場合は、プロパティリストを使用する必要がありますか?またはSQLLite3?

それ以外の場合、クラスモデルをアーカイブする必要がありますか? SQLLite3を使用しますか?

編集:私は誤ってアプリに関するいくつかの重要な情報を省略しました。実際、私のアプリには、集約された関係を持つ2つのデータモデルがあります。したがって、NSStringとNSDateを持つ最初のデータモデル(DataAと呼びます)には、NSStringとNSArrayで構成される2番目のデータモデル(DataBと呼びます)への参照もあります。そのため、今はもう少し複雑になっています。 DataBのオブジェクトが削除された場合、それはもちろんDataAに存在しなくなるはずです(ただし、DataAの残りの部分はそのままにしておく必要があります)

17
Peter Warbo

この種のデータは、保存と取得が非常に簡単であるように思われ、非常に複雑なオブジェクトグラフなどの他の依存関係はありません。

このデータはフラットファイルまたはNSUserDefaultsに保存する必要があります。

NSCodingプロトコルを使用したオブジェクトアーカイブを使用した、両方の例を示します。

@interface ApplicationData <NSCopying, NSCoding> {}

@property (nonatomic, strong) NSDate *someDate;
@property (nonatomic, strong) NSDate *someOtherDate;

@property (nonatomic, copy) NSString *someString;
@property (nonatomic, copy) NSString *someOtherString;

@end

@implementation ApplicationData

@synthesize someDate = _someDate, someOtherDate = _someOtherDate, someString = _someString, someOtherString = _someOtherString;

- (NSArray *)keys {
   static dispatch_once_t once;
   static NSArray *keys = nil;
   dispatch_once(&once, ^{
      keys = [NSArray arrayWithObjects:@"someString", @"someOtherString", @"someDate", @"someOtherDate", nil];
  });
   return keys;
}

- (id) copyWithZone:(NSZone *) zone {
    ApplicationData *data = [[[self class] allocWithZone:zone] init];
    if(data) {
        data.someString = _someString;
        data.someOtherString = _someOtherString;     

        data.someDate = _someDate;
        data.someOtherDate = _someOtherDate;
        //...
    }
    return data;
 }

 - (void) encodeWithCoder:(NSCoder *) coder {
     [super encodeWithCoder:coder];

     NSDictionary *pairs = [self dictionaryWithValuesForKeys:[self keys]];

     for(NSString *key in keys) {
        [coder encodeObject:[pairs objectForKey:key] forKey:key];
     }
  }


  - (id) initWithCoder:(NSCoder *) decoder {
     self = [super initWithCoder:decoder];
     if(self) {
        for(NSString *key in [self keys]) {
           [self setValue:[decoder decodeObjectForKey:key] forKey:key];
        }
     }
     return self;
  }

  @end

次に、アプリケーションデリゲートで、次のように実行できます。

@interface AppDelegate (Persistence)

@property (nonatomic, strong) ApplicationData *data;

- (void)saveApplicationDataToFlatFile;
- (void)loadApplicationDataFromFlatFile;
- (void)saveApplicationDataToUserDefaults;
- (void)loadApplicationDataFromUserDefaults;

@end

@implementation AppDelegate (Persistence) 
@synthesize data;

- (NSString *)_dataFilePath {
   static NSString *path = nil;
   static dispatch_once_t once;
   dispatch_once(&once, ^{
     path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) stringByAppendingPathComponent:@"xAppData.dat"];
   });
   return path;
}

- (void)loadApplicationDataFromUserDefaults {        
   NSData *archivedData = [[NSUserDefaults standardUserDefaults] objectForKey:@"appData"];
   self.data = [NSKeyedUnarchiver unarchiveObjectWithData:archivedData];
}

- (void)saveApplicationDataToUserDefaults {
   NSData *archivedData = [NSKeyedArchiver archivedDataWithRootObject:self.data];
   [[NSUserDefaults standardUserDefaults] setObject:archivedData forKey:@"appData"];
   [[NSUserDefaults standardUserDefaults] synchronize];
}

- (void)loadApplicationDataFromFlatFile {
   NSData *archivedData = [NSData dataWithContentsOfFile:[self _dataFilePath]];
   self.data = [NSKeyedUnarchiver unarchiveObjectWithData:archivedData];
}

- (void)saveApplicationDataToFlatFile {  
   NSData *archivedData = [NSKeyedArchiver archivedDataWithRootObject:self.data];
   [archivedData writeToFile:[self _dataFilePath] atomically:YES];
}

@end

免責事項:私はこのコードをテストしていません。

18
Jacob Relkin

NSUserDefaultsを使用することをお勧めします。これは、アプリやアプリ関連のデータに関連する情報を保存するための最良のアプローチです。 ドキュメント を確認してください!!

1
Legolas

NSUserDefaultは、限られたデータセットしかない場合に適しています。ただし、フィルタリングとフェッチを検討する場合は、オブジェクトを格納するためにコアデータを確認する必要があります。

オブジェクトグラフが最小であっても、キャッシュされたオブジェクト管理と無料の元に戻す/やり直しの管理が得られます。

1
Sylvain G.