Стратегия постоянного хранения iOS - PullRequest
17 голосов
/ 04 января 2012

Я разрабатываю приложение, которое будет сохранять данные в локальной файловой системе. Данные, которые будут сохранены, будут в основном NSString и NSDate. Данные не будут сохраняться так часто, возможно, новые данные будут вводиться 10 раз при обычном использовании. Данные также должны, конечно, быть извлекаемыми (CRUD)

Как мне сохранить эти данные? Прежде всего, нужно ли моделировать эти объекты? Если нет, я должен использовать списки свойств? Или SQLLite3?

Иначе я должен архивировать модели классов? Использовать SQLLite3?

РЕДАКТИРОВАТЬ: я случайно пропустил некоторую важную информацию о приложении. На самом деле мое приложение будет иметь 2 модели данных, которые имеют совокупные отношения. Итак, моя первая модель данных (давайте назовем ее DataA), которая будет иметь NSString, а NSDate также будет иметь ссылку на вторую модель данных (назовем ее DataB), которая сама состоит из NSString и NSArray. Так что теперь все немного сложнее. Если объект из DataB удаляется, он, конечно, должен перестать существовать в DataA (но остальная часть DataA должна быть оставлена ​​нетронутой)

Ответы [ 3 ]

18 голосов
/ 04 января 2012

Данные такого типа, по-видимому, очень просты для хранения и извлечения и не имеют никаких других зависимостей, таких как ужасно сложный граф объектов.

Вы должны хранить эти данные в плоском файле или в 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

Отказ от ответственности: я не проверял этот код.

1 голос
/ 04 января 2012

NSUserDefault - хороший выбор, если у вас есть только ограниченный набор данных.Но если вы подумаете о фильтрации и извлечении, вам следует обратиться к Core Data для хранения объектов.

Даже если граф объектов минимален, вы получите управление кэшированными объектами и бесплатное управление отменой / повторением.

1 голос
/ 04 января 2012

Я бы посоветовал вам пойти с NSUserDefaults.Это, безусловно, лучший подход для хранения информации, относящейся к вашему приложению и любым данным, связанным с приложением.Проверьте документацию !!

...