什么因素会导致NSUserDefaults被清除?

7
我一直在收到有关我的应用程序的奇怪报告,其中存储在 NSUserDefaults 中的应用程序设置被清除了。所有的报告都出现在iOS 7上。
我知道你可以通过卸载或调用来手动清除NSUserDefaults
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];

[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];

但是,应用程序清除其设置的其他已知原因有哪些?

1
在我的越狱iPhone上,许多应用程序在系统崩溃后会失去它们的NSUserdefaults。你有检查过这是否是来自越狱的iPhone吗? - Selvin
1
不要忘记,为了立即保存默认设置,您需要调用-(void)synchronize。[[NSUserDefaults standardDefaults] synchronize]; - Karim
1
除此之外,我能知道您在默认值中存储了哪些其他值吗?如果iOS检测到内存压力,它可能会清除NSUserDefaults,但不仅限于此。因此,请确保您不要在默认值中存储大块数据。最好使用NSDocumentsDirectory来处理大量数据。 - Balram Tiwari
1
自 iOS 7 起,当应用进入后台时,NSUserDefaults 不会自动同步。所以,真正的问题是你需要在应用进入后台时(或其他时机)调用[[NSUserDefaults standardUserDefaults] synchronize]; 吗?也就是说,真正的问题是设置一开始没有被正确保存吗? - DarkDust
1
你能解决这个问题吗?我有同样的问题已经有一段时间了,找不到问题的根源。 - Daniel
显示剩余7条评论
1个回答

1
如果您不想让数据被删除,那么您应该使用KeyChain来存储值。一个好的开始方式是:使用KeyChain
下面我提供了一个示例代码,演示如何从KeyChain中存储和获取数据。

导入所需框架

#import <Security/Security.h>

将值存储到KeyChain中

NSString *key = @"Full Name";
NSString *value = @"Steve Jobs";
NSData *valueData = [value dataUsingEncoding:NSUTF8StringEncoding];
NSString *service = [[NSBundle mainBundle] bundleIdentifier];
NSDictionary *secItem = @{
                              (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword, (__bridge id)kSecAttrService : service,
                              (__bridge id)kSecAttrAccount : key,
                              (__bridge id)kSecValueData : valueData,
                              };
    CFTypeRef result = NULL;
    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)secItem, &result);
if (status == errSecSuccess)
{
     NSLog(@"Successfully stored the value");
}
else{
     NSLog(@"Failed to store the value with code: %ld", (long)status);
}

从KeyChain中获取值
NSString *keyToSearchFor = @"Full Name";
NSString *service = [[NSBundle mainBundle] bundleIdentifier];
NSDictionary *query = @{
                        (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword, (__bridge id)kSecAttrService : service,(__bridge id)kSecAttrAccount : keyToSearchFor,
                        (__bridge id)kSecReturnAttributes : (__bridge id)kCFBooleanTrue, };
CFDictionaryRef valueAttributes = NULL;
OSStatus results = SecItemCopyMatching((__bridge CFDictionaryRef)query,
                                       (CFTypeRef *)&valueAttributes);
NSDictionary *attributes =
(__bridge_transfer NSDictionary *)valueAttributes;
if (results == errSecSuccess){
    NSString *key, *accessGroup, *creationDate, *modifiedDate, *service;
    key = attributes[(__bridge id)kSecAttrAccount];
    accessGroup = attributes[(__bridge id)kSecAttrAccessGroup]; creationDate = attributes[(__bridge id)kSecAttrCreationDate]; modifiedDate = attributes[(__bridge id)kSecAttrModificationDate]; service = attributes[(__bridge id)kSecAttrService];
    NSLog(@"Key = %@\n \ Access Group = %@\n \
          Creation Date = %@\n \
          Modification Date = %@\n \
          Service = %@", key, accessGroup, creationDate, modifiedDate, service);
}
else
{
    NSLog(@"Error happened with code: %ld", (long)results);
}

1
虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅有链接的答案可能会失效。 - LittleBobbyTables - Au Revoir
好主意 @LittleBobbyTables,我打算写一个例子,谢啦! :) - E-Riddie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接