2017-02-24 158 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

相关问题