iOS持久存储策略

时间:2012-01-04 13:15:24

标签: objective-c cocoa-touch persistence save

我正在开发一个将数据保存到本地文件系统的应用程序。将保存的数据主要是NSString和NSDate。通常不会保存数据,在典型使用情况下可能会输入10次新数据。数据当然也应该是可检索的(CRUD)

我应该如何保存这些数据?首先是有必要对这些物体进行建模吗?如果不是我应该使用属性列表?还是SQLLite3?

否则我应该归档班级模型吗?使用SQLLite3?

编辑:我不小心遗漏了一些有关该应用的重要信息。实际上我的应用程序将拥有2个具有聚合关系的数据模型。所以我的第一个数据模型(让我们称之为DataA)将有一个NSString和NSDate也将引用第二个数据模型(让我们称之为DataB),它本身将由NSString和NSArray组成。所以现在变得有点复杂了。如果DataB中的对象被删除,它当然应该不再存在于DataA中(但DataA的其余部分应保持不变)

3 个答案:

答案 0 :(得分:18)

这种数据似乎非常易于存储和检索,并且没有任何其他依赖项,例如可怕的复杂对象图。

您应将此数据存储在平面文件或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 :(得分:1)

我建议您选择NSUserDefaults。这肯定是存储与您的应用和任何应用相关数据相关的信息的最佳方法。检查documentation !!

答案 2 :(得分:1)

如果您只有一组有限的数据,那么NSUserDefault是不错的选择。 但是如果你考虑过滤和提取,那么你应该看看Core Data来存储对象。

即使对象图最小,您也可以获得缓存对象管理和免费撤消/重做管理。