2012-03-13 94 views
30

在我开始之前,我应该告诉你,这个只有发生在iOS 5.1中。在最近的更新之前,这从来没有发生过,并且在任何其他版本上都不会发生。这就是说,这是发生了什么事。为什么在创建UIWebView时清除NSUserDefaults会导致EXC_CRASH?

当用户退出我的应用程序时,发生的一件事是所有NSUserDefaults都被删除。而不是手动删除每一个关键我可能会添加到用户的默认,我只是完全删除所有NSUserDefaults的,使用this SO question建议的方法:

NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier]; 
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain]; 

有什么事虽然发生的,是每次我尝试删除NSUserDefaults后创建一个UIWebView,我得到一个EXC_CRASH (SIGABRT)。当我打电话给[[UIWebView alloc] initWithFrame:frame]时发生了这次事故。奇怪的权利?完全退出并重新打开应用程序允许再次创建UIWebView

因此,我设法弄清楚删除默认值会导致UIWebView问题,但可以肯定的是,我为-[NSUserDefaults setObject:forKey:]添加了一个符号断点。

-[NSUserDefaults setObject:forKey:] breakpoint

创建UIWebView确实触发断点。

戳通过崩溃日志让我异常的原因:

-[__NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: WebKitLocalStorageDatabasePathPreferenceKey) 

而这里的堆栈跟踪的开头:

0 CoreFoundation 0x3340688f __exceptionPreprocess + 163 
1 libobjc.A.dylib 0x37bd4259 objc_exception_throw + 33 
2 CoreFoundation 0x33406789 +[NSException raise:format:] + 1 
3 CoreFoundation 0x334067ab +[NSException raise:format:] + 35 
4 CoreFoundation 0x3337368b -[__NSCFDictionary setObject:forKey:] + 235 
5 WebKit 0x3541e043 -[WebPreferences _setStringValue:forKey:] + 151 
6 UIKit 0x32841f8f -[UIWebView _webViewCommonInit:] + 1547 
7 UIKit 0x328418d7 -[UIWebView initWithFrame:] + 75 
8 MyApp 0x0007576f + 0 
9 UIKit 0x326d4dbf -[UIViewController view] + 51 
10 UIKit 0x327347e5 -[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:] + 93 
11 UIKit 0x32734783 -[UITabBarController transitionFromViewController:toViewController:] + 31 
12 UIKit 0x327340bd -[UITabBarController _setSelectedViewController:] + 301 
13 UIKit 0x327bd5d9 -[UITabBarController _tabBarItemClicked:] + 345 

我在做什么,现在,什么工作,只是跟踪我设置的NSUserDefaults键,并在需要时手动删除它们。但总有一种风险,我可能会忘记一个敏感的钥匙,所以只需清除所有的NSUserDefaults就可以让我更加明智。所以,我想知道为什么我不能那样做。这是一个错误还是我做错了什么?

如果您想了解更多信息,请告诉我!谢谢。

编辑:做[[NSUserDefaults standardUserDefaults] synchronize]删除后全部NSUserDefaults没有帮助。

+0

显示您在同一控制器中使用的更多代码。 UIWebView是否依赖于首选项中存储的任何值? – WrightsCS 2012-03-13 06:54:40

+0

“EXC_CRASH”独立于哪个控制器加载UIWebView而发生。我把所有的UIWebView包装在'@try {} @catch {}'块中,每一个都给了我相同的例外。我想不出任何UIWebView可能依赖的值,特别是在初始化时。如果你仍然喜欢一个包含UIWebView的控制器的代码,请告诉我。 – cbrauchli 2012-03-13 07:04:47

+0

是的,发布任何和所有相关的代码。 – WrightsCS 2012-03-13 16:35:05

回答

24

我也看到了这个问题,我想你必须先创建一个UIWebView,然后清除用户默认值才会发生。一个干净的项目会导致iOS5.1崩溃,这在iOS5中可以正常工作。0和更早版本:

UIWebView *webView = [[UIWebView alloc] init]; 
[webView release]; 

[[NSUserDefaults standardUserDefaults] setPersistentDomain:[NSDictionary dictionary] forName:[[NSBundle mainBundle] bundleIdentifier]]; 

UIWebView *anotherWebView = [[UIWebView alloc] init]; 
[anotherWebView release]; 

我可以解决通过这样做,而不是崩溃,这避免了必须记住你所有的设置键:

id workaround51Crash = [[NSUserDefaults standardUserDefaults] objectForKey:@"WebKitLocalStorageDatabasePathPreferenceKey"]; 
NSDictionary *emptySettings = (workaround51Crash != nil) 
       ? [NSDictionary dictionaryWithObject:workaround51Crash forKey:@"WebKitLocalStorageDatabasePathPreferenceKey"] 
       : [NSDictionary dictionary]; 
[[NSUserDefaults standardUserDefaults] setPersistentDomain:emptySettings forName:[[NSBundle mainBundle] bundleIdentifier]]; 

任何人看到做这种方式的任何问题?

+0

啊,是的,这再现了错误。谢谢你的提示!此外,这似乎是避免崩溃的合理方法;我一直在使用它,并没有发现任何问题。干杯:) – cbrauchli 2012-03-16 19:09:54

+0

只是这样做,它似乎工作。我确信在管理用户注销时我们都会遇到这个问题。 – 2012-07-05 11:43:20

+1

这是一个很好的解决方法,但看起来太具体,并且可能无法防范系统可能依赖的其他未知密钥。花了一些时间,但我收集了每个我使用的密钥,并在用户注销时手动删除每个密钥。 – Snowman 2012-09-05 12:15:17

3

这听起来像你正在删除某种私人偏好,这可能是一个新的bug,无论是NSUserDefaults(你不应该能够删除它)或UIWebView(它应该应对缺少的条目)。

您是否尝试过使用其他答案的方法(设置空白字典?)。这是否给出了相同的结果?

如果您获取NSUserDefaults的字典表示形式,获取所有的键,并遍历这些键,删除对象? (让我知道你是否需要一个代码示例)。

+0

这很有道理。我曾尝试另一种设置空白字典的方法无济于事。我只是尝试了通过遍历所有键的建议,并产生相同的结果。看看字典,我看到一些我没有设置的密钥,主要是格式“WebKit *”。 'WebKitLocalStorageDatabasePathPreferenceKey'就是其中之一。 – cbrauchli 2012-03-13 07:22:48

+0

这听起来像是一个bug。如果你在iOS 5.0或更早的版本上运行,你看到的关键是不同的?提交错误时需要这些信息。 – jrturton 2012-03-13 07:57:16

+1

对不起,延迟回复你。我创建了一个干净的应用程序,它在NSUserDefaults中设置一个键,然后删除所有的NSUserDefaults,然后尝试创建UIWebView。我一直无法重现那里的错误,所以我只能假设在我的应用程序中出现其他问题。我将提交一份错误报告并继续尝试重现该错误。我会在这里发布任何更新。谢谢! – cbrauchli 2012-03-15 21:08:31

0

它为我

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 

NSDictionary *userDefaultsDictionary = [userDefaults dictionaryRepresentation]; 
NSString *strWebDatabaseDirectory = [userDefaultsDictionary objectForKey:@"WebDatabaseDirectory"]; 
NSString *strWebKitLocalStorageDatabasePathPreferenceKey = [userDefaultsDictionary objectForKey:@"WebKitLocalStorageDatabasePathPreferenceKey"]; 

[userDefaults removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]]; 

if (strWebDatabaseDirectory) { 
    [userDefaults setObject:strWebDatabaseDirectory forKey:@"WebDatabaseDirectory"];} 
if (strWebKitLocalStorageDatabasePathPreferenceKey) { 
    [userDefaults setObject:strWebKitLocalStorageDatabasePathPreferenceKey forKey:@"WebKitLocalStorageDatabasePathPreferenceKey"];} 

[userDefaults synchronize]; 
0
简单

这将是使用下面的代码:

[self saveValue:@"" forKey:@"WebKitLocalStorageDatabasePathPreferenceKey"]; 
[[NSUserDefaults standardUserDefaults] synchronize]; 

更容易。

相关问题