Objective c iOS持久存储策略
我正在开发一个将数据保存到本地文件系统的应用程序。将保存的数据主要是NSString和NSDate。数据通常不会保存,新数据可能会在一次典型使用中输入10次。当然,数据也应该是可检索的(CRUD) 我应该如何保存这些数据?首先,有必要对这些对象建模吗?如果没有,我应该使用属性列表吗?还是SQLLite3 我还应该归档类模型吗?使用SQLLite3Objective c iOS持久存储策略,objective-c,cocoa-touch,persistence,save,Objective C,Cocoa Touch,Persistence,Save,我正在开发一个将数据保存到本地文件系统的应用程序。将保存的数据主要是NSString和NSDate。数据通常不会保存,新数据可能会在一次典型使用中输入10次。当然,数据也应该是可检索的(CRUD) 我应该如何保存这些数据?首先,有必要对这些对象建模吗?如果没有,我应该使用属性列表吗?还是SQLLite3 我还应该归档类模型吗?使用SQLLite3 编辑:我不小心遗漏了一些有关该应用程序的重要信息。实际上,我的应用程序将有两个数据模型,它们具有聚合关系。因此,我的第一个数据模型(我们称之为Data
编辑:我不小心遗漏了一些有关该应用程序的重要信息。实际上,我的应用程序将有两个数据模型,它们具有聚合关系。因此,我的第一个数据模型(我们称之为DataA)将有一个NSString,NSDate也将有一个对第二个数据模型(我们称之为DataB)的引用,它本身将由一个NSString和一个NSArray组成。所以它现在变得有点复杂了。如果DataB中的一个对象被删除,它当然应该不再存在于DataA中(但DataA的其余部分应该保持不变)这种数据似乎很容易存储和检索,并且没有任何其他依赖项,例如非常复杂的对象图 您应该将此数据存储在平面文件或
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
免责声明:我尚未测试此代码。我建议您使用
NSUserDefaults
。这无疑是存储应用程序相关信息和任何应用程序相关数据的最佳方法。检查一下 NSUserDefault是一个很好的选择,如果您只有有限的数据集。
但是,如果考虑筛选和获取,则应该查看核心数据来存储对象。
即使对象图是最小的,您也可以获得缓存对象管理和免费的撤消/重做管理。如果数据量不是很大,正如您所说。。您可以使用NSUserDefaults…它简单易用。感谢您的详细回答。实际上,我的应用程序将有两个数据模型,它们具有聚合关系。因此,我的第一个数据模型(我们称之为DataA)将有一个NSString,NSDate也将有一个对第二个数据模型(我们称之为DataB)的引用,它本身将由一个NSString和一个NSArray组成。所以它现在变得有点复杂了。如果数据中的对象被删除,它当然应该在数据中不再存在。@PeterWarbo如果是这样,我建议您使用核心数据,因为这是执行级联关系规则等操作的最简单方法。它的实现应该非常简单,尽管我对仅仅为了实现这一点而设置核心数据堆栈的权衡持怀疑态度……因此基本上,它可以归结为使用我的数据模型存档还是使用核心数据?@PeterWarbo-Yep。在这种情况下,我不建议直接使用
sqlite
。@PeterWarbo,因为您完全需要使用SQL过滤数据,并且还需要通过删除核心数据中间人来提高性能。到目前为止,我还没有遇到满足这些条件的情况,所以如果可以的话,我会尽量远离它。更不用说sqlite3
API是一个让人头疼的问题。
@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