NSInternalInconsistencyException with NSUserDefaults when using method setValue: forPath
My code is as follows:
NSMutableDictionary *configure = [[NSUserDefaults standardUserDefaults] objectForKey:@"configure"];
if (!configure){
configure = [NSMutableDictionary dictionary];
[configure setValue:[NSMutableDictionary dictionary] forKeyPath:@"select"] ;
[configure setValue:[NSMutableDictionary dictionary] forKeyPath:@"select.around"];
[configure setValue: @"All" forKeyPath:@"select.around.name"];
[[NSUserDefaults standardUserDefaults] setObject:configure forKey:@"configure"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
NSString *keyPath = @"configure.select.around";
NSMutableDictionary *aroundConfigure = [[[NSUserDefaults standardUserDefaults] valueForKeyPath:keyPath] mutableCopy];
[aroundConfigure setObject:@"" forKey:@"name"];
[[NSUserDefaults standardUserDefaults] setValue:aroundConfigure forKeyPath:keyPath];
It's crashing every time with the error below:
** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
*** Call stack at first throw:
(
0 CoreFoundation 0x00daebe9 __exceptionPreprocess + 开发者_如何学JAVA185
1 libobjc.A.dylib 0x00f035c2 objc_exception_throw + 47
2 CoreFoundation 0x00d67628 +[NSException raise:format:arguments:] + 136
3 CoreFoundation 0x00d6759a +[NSException raise:format:] + 58
4 CoreFoundation 0x00dad401 -[__NSCFDictionary setObject:forKey:] + 209
5 Foundation 0x0004b34d -[NSObject(NSKeyValueCoding) setValue:forKeyPath:] + 399
6 Foundation 0x0004b34d -[NSObject(NSKeyValueCoding) setValue:forKeyPath:] + 399
7 Untitled 0x00002429 -[UntitledAppDelegate application:didFinishLaunchingWithOptions:] + 774
8 UIKit 0x002b81fa -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1163
9 UIKit 0x002ba55e -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 439
10 UIKit 0x002c4db2 -[UIApplication handleEvent:withNewEvent:] + 1533
11 UIKit 0x002bd202 -[UIApplication sendEvent:] + 71
12 UIKit 0x002c2732 _UIApplicationHandleEvent + 7576
13 GraphicsServices 0x016e4a36 PurpleEventCallback + 1550
14 CoreFoundation 0x00d90064 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
15 CoreFoundation 0x00cf06f7 __CFRunLoopDoSource1 + 215
16 CoreFoundation 0x00ced983 __CFRunLoopRun + 979
17 CoreFoundation 0x00ced240 CFRunLoopRunSpecific + 208
18 CoreFoundation 0x00ced161 CFRunLoopRunInMode + 97
19 UIKit 0x002b9fa8 -[UIApplication _run] + 636
20 UIKit 0x002c642e UIApplicationMain + 1160
21 Untitled 0x00002100 main + 102
22 Untitled 0x00002091 start + 53
)
terminate called after throwing an instance of 'NSException'
I know that setObject:forKey:
should used with a mutable dictonary . Is there any problem using KVO with NSUserDefaults? By the way, the platform I use is iPhone.
Your code isn't doing what you think it is doing:
NSMutableDictionary *configure = [[NSUserDefaults standardUserDefaults] objectForKey:@"configure"];
This sets configure
to be the value of your standard defaults to the value of the key configure
configure = [NSMutableDictionary dictionary];
This sets configure
to a new, empty dictionary, not the one you got from User defaults
[configure setValue:[NSMutableDictionary dictionary] forKeyPath:@"select"] ;
You now put an empty dictionary as the value for the key select
[configure setValue:[NSMutableDictionary dictionary] forKeyPath:@"select.around"];
You are adding another empty dictionary for this key path
[configure setValue: @"All" forKeyPath:@"select.around.name"];
And you are setting a string value for this key path
[[NSUserDefaults standardUserDefaults] setObject:configure forKey:@"configure"];
You are now putting this odd dictionary into NSUserDefaults
[[NSUserDefaults standardUserDefaults] synchronize];
NSString *keyPath = @"configure.select.around";
NSMutableDictionary *aroundConfigure = [[[NSUserDefaults standardUserDefaults] valueForKeyPath:keyPath] mutableCopy];
This is just an empty mutable dictionary
[aroundConfigure setObject:@"" forKey:@"name"];
You are setting an empty string for some key in this dictionary
[[NSUserDefaults standardUserDefaults] setValue:aroundConfigure forKeyPath:keyPath];
And then you set this odd dictionary into the the user defaults.
Which is all very confusing.
What is it that you are trying to do?
Edited to add
There's no point providing code if you've "simplified" it we can't see what it's supposed to do.
Your app is crashing because you are trying to change a key value pair of a NSDictionary which is immutable instead of a NSMutableDictionary. See line 6 of your trace.
Since you've provided "simplified" code - I don't know where you are doing this.
Today i also faced this problem because i am making data in dictionary like this
NSMutableDictionary *Dic =[myMutableAry objectAtIndex:0];
after getting data when i am updating my dic value then getting crash
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
Then i did got solution after a lot of research , so just do one thing
NSMutableDictionary *Dic = [NSMutableDictionary dictionaryWithDictionary:[myMutableAry objectAtIndex:0]];
The way you have used the NSUserDefaults is wrong, NSUserDefaults return a non mutable dictionary. That is the cause of this issue. Therefore, you have to request a mutable object explicitly from NSUserDefaults. Please use the code line below.
NSMutableDictionary *configure = [[[NSUserDefaults standardUserDefaults] objectForKey:@"configure"]mutableCopy];
This work with me. Thanks Good luck :)
精彩评论