2012-03-13 88 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]; 

更容易。

相關問題