2017-02-24 114 views
0

我有以下功能:崩潰發生時嘗試設置同步或NSUserDefaults的

-(int) getCounter:(BOOL)isIncrease { 

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 
    NSNumber *counter = [userDefaults valueForKey:kCounter]; 

    int intCounter; 
    if (counter == nil){ 
     intCounter = 0; 
    } else { 
     intCounter = [counter intValue]; 
    } 
    if (isIncrease){ 
     intCounter++; 
     [userDefaults setObject:[NSNumber numberWithInt:intCounter] forKey:kCounter]; 
     [userDefaults synchronize]; 
    }   
    return intCounter; 
} 

它看起來簡單明瞭。

不過有時我獲得以下的面料例外:

#11. Crashed: com.my.app 
0 libobjc.A.dylib    0x1866def70 objc_msgSend + 16 
1 CoreFoundation     0x187c1190c -[CFPrefsPlistSource synchronize] + 96 
2 CoreFoundation     0x187c36674 -[CFPrefsSearchListSource alreadylocked_requestNewData] + 88 
3 CoreFoundation     0x187cd80e8 __58-[_CFXPreferences appSynchronizeWithIdentifier:container:]_block_invoke + 36 
4 CoreFoundation     0x187c38ea4 __108-[_CFXPreferences(SearchListAdditions) withSearchListForIdentifier:container:cloudConfigurationURL:perform:]_block_invoke + 268 
5 CoreFoundation     0x187c3876c normalizeQuintuplet + 360 
6 CoreFoundation     0x187c38d8c -[_CFXPreferences(SearchListAdditions) withSearchListForIdentifier:container:cloudConfigurationURL:perform:] + 104 
7 CoreFoundation     0x187cd8058 -[_CFXPreferences appSynchronizeWithIdentifier:container:] + 292 
8 Foundation      0x1886def90 -[NSUserDefaults(NSUserDefaults) synchronize] + 52 
9 appApp      0x1004b11a4 -[MyProg getCounter:] + 4300083620 
10 appApp      0x1004adb8c -[MyProg callServerWithEventName:value:withDictionary:isEvent:isNewAPI:] + 4300069772 
11 appApp      0x1004ab658 __42-[MyProg sendEvent:withValues:]_block_invoke + 4300060248 
12 libdispatch.dylib    0x186b1e1bc _dispatch_client_callout + 16 
13 libdispatch.dylib    0x186b2af94 _dispatch_continuation_pop + 576 
14 libdispatch.dylib    0x186b37634 _dispatch_source_latch_and_call + 204 
15 libdispatch.dylib    0x186b20160 _dispatch_source_invoke + 820 
16 libdispatch.dylib    0x186b2c210 _dispatch_queue_serial_drain + 468 
17 libdispatch.dylib    0x186b219a4 _dispatch_queue_invoke + 652 
18 libdispatch.dylib    0x186b2c8d8 _dispatch_queue_override_invoke + 360 
19 libdispatch.dylib    0x186b2e34c _dispatch_root_queue_drain + 572 
20 libdispatch.dylib    0x186b2e0ac _dispatch_worker_thread3 + 124 
21 libsystem_pthread.dylib  0x186d272a0 _pthread_wqthread + 1288 
22 libsystem_pthread.dylib  0x186d26d8c start_wqthread + 4 

就以9號線一看:

9 appApp      0x1004b11a4 -[MyProg getCounter:] + 4300083620 

有時它失敗的:[NSUserDefaults(NSUserDefaults) synchronize] 有時上:[NSUserDefaults(NSUserDefaults) setObject:forKey:]

有人可以解釋爲什麼我會發生這種事故,以及如何避免它?

我在我的代碼的很多地方使用UserDefaults,但在上述函數中發生崩潰。

有什麼建議嗎?

[EDIT 1]

// in init: 
mBackgroundQueue = dispatch_queue_create("com.my.app", NULL); 

根函數我請getCounter

- (void) sendEvent{ 

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 
       (int64_t)(0.1f * NSEC_PER_SEC)), 
    mBackgroundQueue, 
^{     
    [self callServerWithEventName:eventName ...         
        withDictionary:nil 
          isEvent:YES 
         isNewAPI:YES]; 
} 

callServerWithEventName我打電話[self getCounter];

[EDIT 2]

崩潰發生在setObject:forKey:]

#14. Crashed: com.my.app 
0 libdispatch.dylib    0x184d397bc dispatch_group_enter + 108 
1 CoreFoundation     0x185e27610 -[CFPrefsPlistSource sendFullyPreparedMessage:toConnection:settingValue:forKey:retryCount:] + 240 
2 CoreFoundation     0x185e27c48 -[CFPrefsPlistSource sendMessageSettingValue:forKey:] + 388 
3 CoreFoundation     0x185e26620 -[CFPrefsPlistSource alreadylocked_setValues:forKeys:count:] + 864 
4 CoreFoundation     0x185ee72a8 -[CFPrefsSource setValues:forKeys:count:removeValuesForKeys:count:] + 264 
5 CoreFoundation     0x185e4dafc -[CFPrefsSearchListSource alreadylocked_setValues:forKeys:count:] + 428 
6 CoreFoundation     0x185ee72a8 -[CFPrefsSource setValues:forKeys:count:removeValuesForKeys:count:] + 264 
7 CoreFoundation     0x185ee7444 -[CFPrefsSource setValue:forKey:] + 60 
8 CoreFoundation     0x185e505c0 __108-[_CFXPreferences(SearchListAdditions) withSearchListForIdentifier:container:cloudConfigurationURL:perform:]_block_invoke + 268 
9 CoreFoundation     0x185e4fe88 normalizeQuintuplet + 360 
10 CoreFoundation     0x185e504a8 -[_CFXPreferences(SearchListAdditions) withSearchListForIdentifier:container:cloudConfigurationURL:perform:] + 104 
11 CoreFoundation     0x185eece7c -[_CFXPreferences setValue:forKey:appIdentifier:container:configurationURL:] + 276 
12 Foundation      0x1868a4eb8 -[NSUserDefaults(NSUserDefaults) setObject:forKey:] + 68 
13 ifyApp      0x1004a518c -[MyProg getCounter:] + 4300362124 
14 ifyApp      0x1004a1b8c -[MyProg callServerWithEventName:value:withDictionary:isEvent:isNewAPI:] + 4300348300 
15 ifyApp      0x10049f658 __42-[MyProg sendEvent:withValues:]_block_invoke + 4300338776 

感謝,

+0

'setObject:'是一個'NSUserDefaults'方法 – snaggs

+0

是的,對不起,我忘了注意它已經在你的問題。你可以嘗試通過'objectForKey:'檢索值,並讓我們知道它是否仍然崩潰? – viral

+0

@iOSAppDev我有1M的客戶,有時會發生這種情況。據我所知'NSUserDefaults'是一個單身人士,它真的很奇怪 – snaggs

回答

-1

對我來說,它看起來像該對象被釋放,你是無論如何調用getCounter方法。 這就是爲什麼它顯示這個奇怪的第9行。

你可以分享更多的代碼,你可以使用getCounter方法以及如何創建相應的類實例。

+0

添加了root方法 – snaggs

+0

我假設你調用[self getCounter] self時不存在。 你能分享整張照片嗎?你在哪裏創建自我的實例?它的可見度範圍是什麼? – RomanN

+0

它不是'self'的問題。看看堆棧跟蹤。 'getCounter'內發生崩潰 – snaggs

0

的問題是,你從後臺排隊叫「getCounter」與延遲,當您嘗試設置「intCounter」

+1

在這種情況下,'[NSNumber numberWithInt:intCounter]'是'1' ...即使它是零,它也不會崩潰。 – viral

2

堆棧跟蹤顯示你的崩潰在synchronize由於發生鎖定衝突也可能是零因爲你太頻繁地調用它。沒有必要撥打synchronize,取消通話應該可以解決問題。

您可以通過使用integerForKey & setIntegerForKey而非objectForKey(或者valueForKey這是不正確的)和setObjectForKey大大簡化你的代碼。

- (NSInteger) getCounter:(BOOL)isIncrease { 
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    NSInteger counter = [defaults integerForKey:kCounter]; 

    if (isIncrease) { 
     counter++; 
     [defaults setIntegerForKey:kCounter]; 
    } 

    return counter; 
} 
+0

我同意「同步」這個觀點不需要被調用。但是,我懷疑'integerForKey'&'setIntegerForKey'服務器\解決崩潰的任何目的。 – viral

+1

不,崩潰發生是由於不必要的同步調用導致鎖定問題。我簡單地藉此機會展示了一個簡單明瞭的解決方案,與原來的代碼不同,它不必要地複雜並且使用不正確的調用。 – Paulw11

+0

+1的努力,但你確定'synchronize'正在讓它崩潰。我的意思是它只是製作,我們沒有辦法親自測試它,除了用改動重新提交應用程序。 – viral