首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSUserDefaults对NSKeyedArchiver

NSUserDefaults对NSKeyedArchiver
EN

Stack Overflow用户
提问于 2011-07-28 11:47:46
回答 3查看 2.1K关注 0票数 5

我认为这是一个关于数据管理的初学者问题。

我有一个应用程序,加载和保存不同的txt文件。我想给每个txt文件一些没有保存在txt文件中的特性,如名称、样式、颜色等。

到目前为止,我所做的是拥有一个NSMutableArray *myLibrary,在这里我将保存所有这些引用。数组如下所示:

每个txt文件的NSMutableArrays

  • in

  • --一个对象被添加到myLibrary

  • --每个对象包含几个NSStrings、NSUInteger、BOOLs,以及一些my子类,用于这些对象。

-(id)initWithCoder:(NSCoder *)aDecoder;-(void)encodeWithCoder:(NSCoder *)aCoder;

现在,我的大问题是,坚持这些数据的最好和最安全的方法是什么。到目前为止,我已经使用过NSKeyedArchiver,但是用户已经报告了数据丢失,并且有一种奇怪的情况,即iTunes同步据称导致了数据的混乱。NSUserDefaults有什么保护程序吗?每次用户进行更改时,我都会保存myLibrary.dat,所以我真的不明白为什么不应该100%保存。如有任何建议/建议/解释,将不胜感激!

下面是我编写和读取myLibrary.Dat的代码:

代码语言:javascript
复制
   -(NSString*)documentsDirectory
{
    NSLog(@"documentsDirectory");
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents directory
    return documentsDirectory;
}

-(void)saveLibraryDat {

    NSLog(@"Saving myLibrary.dat...");
    NSString *filePath = [[self documentsDirectory] stringByAppendingPathComponent:@"myLibrary.dat"];
    BOOL succeed = [[NSKeyedArchiver archivedDataWithRootObject:myLibrary] writeToFile:filePath atomically:YES];
    if (!succeed){ // do something  }

}


-(void)loadLibraryDat {

    NSLog(@"loadLibraryDat");
    NSString *filePath = [[self documentsDirectory] stringByAppendingPathComponent:@"myLibrary.dat"];

    self.myLibrary = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];

    if (self.myLibrary == nil) {
        NSLog(@"myLibrary.dat empty... set up new one");
        [self setupLibrary];
    } else { NSLog(@"Loading myLibrary.dat successful."); }

}

编辑:我的编码器方法如下所示:

代码语言:javascript
复制
 - (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super init];
    if (self) {
        self.titleName = [aDecoder decodeObjectForKey:@"titleName"];
        self.fileName = [aDecoder decodeObjectForKey:@"fileName"];
        self.fileFont = [aDecoder decodeObjectForKey:@"fileFont"];
 self.tabTitles = [aDecoder decodeObjectForKey:@"tabTitles"];
   }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:titleName forKey:@"titleName"];
    [aCoder encodeObject:fileName forKey:@"fileName"];
    [aCoder encodeObject:fileFont forKey:@"fileFont"];
    [aCoder encodeObject:tabTitles forKey:@"tabTitles"];
}

@end

在标头中,这些定义为:

代码语言:javascript
复制
NSString *titleName;
NSString *fileName;
NSString *fileFont;
NSMutableArray *tabTitles;
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-07-28 12:19:41

不要使用NSUserDefaults。这是更多的默认设置,如我是否应该显示窗口X在启动。NSUserDefaults不是为程序数据设计的。您应该像正在做的那样使用NSKeyArchiver。错误很可能发生在myLibrary包含的对象中。

您应该查看(或发布)这些功能:

代码语言:javascript
复制
- (id)initWithCoder:(NSCoder *)coder 
- (void)encodeWithCoder:(NSCoder *)coder

这很可能是你的问题所在。

票数 3
EN

Stack Overflow用户

发布于 2011-07-28 12:20:15

如果用户使用越狱手机,可以访问iOS5下的文档目录,也可以访问任何版本的文档目录。将文件保存到~/Library/Application Support/appname

代码语言:javascript
复制
NSMutableString *path = [[NSMutableString alloc] init];
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSApplicationSupportDirectory, NSUserDomainMask, YES);
[path appendString: [paths objectAtIndex: 0]];
[path appendString: @"/YOURAPPNAME"];

编辑

您发布的代码运行良好,如果数组包含NSCoding支持的数据类型,则不会出现任何问题。作为一种风格,我会用常量作为键,以避免在键中输入愚蠢的字体。例:NSString *const kTitleName = @"kTitleName";在您的@implementation部分上面。

票数 1
EN

Stack Overflow用户

发布于 2016-01-08 22:11:38

正如其他人提到的,考虑到您存储的是应用程序数据而不是简单的默认设置,NSKeyedArchiver是一个比NSUserDefaults更好的解决方案。

关于你的数据丢失问题。

如果应用程序从输入数据到成功调用saveLibraryDat之间崩溃,用户可能会丢失数据。您可能会尝试类似Crashlytics之类的方法来监视最终用户应用程序的崩溃。

如果succeed中的saveLibraryDat是假的,用户也可能丢失数据。用有意义的错误处理替换// do something。也许设备上没有保存数据的空间了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6858424

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档