【问题标题】:NSInternalInconsistencyException with NSUserDefaults when using method setValue: forPath使用方法 setValue 时出现 NSUserDefaults 的 NSInternalInconsistencyException:forPath
【发布时间】:2011-05-23 16:41:29
【问题描述】:

我的代码如下:

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];

每次都会崩溃,出现以下错误:

** 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 + 185
    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'

我知道 setObject:forKey: 应该与可变字典一起使用。将 KVO 与 NSUserDefaults 一起使用有什么问题吗?顺便说一句,我使用的平台是 iPhone。

【问题讨论】:

    标签: iphone nsuserdefaults setvalue


    【解决方案1】:

    你的代码没有做你认为它正在做的事情:

    NSMutableDictionary *configure = [[NSUserDefaults standardUserDefaults] objectForKey:@"configure"];
    

    这会将configure 设置为您的标准默认值,即键configure 的值

    configure = [NSMutableDictionary dictionary];
    

    这会将configure 设置为一个新的空字典,而不是您从用户默认值中获得的字典

    [configure setValue:[NSMutableDictionary dictionary] forKeyPath:@"select"] ;
    

    您现在将一个空字典作为键 select 的值

    [configure setValue:[NSMutableDictionary dictionary] forKeyPath:@"select.around"];
    

    您正在为此键路径添加另一个空字典

    [configure setValue: @"All" forKeyPath:@"select.around.name"];
    

    你正在为这个键路径设置一个字符串值

    [[NSUserDefaults standardUserDefaults] setObject:configure forKey:@"configure"];
    

    你现在将这个奇怪的字典放入 NSUserDefaults

    [[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];
    

    然后你将这个奇怪的字典设置为用户默认值。

    这一切都非常令人困惑。

    你想做什么?

    编辑添加

    如果你已经“简化”了代码,那么提供代码是没有意义的,我们看不到它应该做什么。

    您的应用程序崩溃了,因为您试图更改 NSDictionary 的键值对,该键值对是不可变的,而不是 NSMutableDictionary。请参阅跟踪的第 6 行。

    由于您提供了“简化”代码 - 我不知道您在哪里执行此操作。

    【讨论】:

    • 嗨,abizern,我打算在初始化时创建一个字典 {"configure":{"select":{"around":{"name":"All" }}}}应用程序,然后将 keypath configure.selelct.around.name 设置为空字符串。我已经简化了代码。所以它看起来毫无意义。我只想知道它为什么会崩溃。谢谢。
    • 一个,我认为你应得的。我所需要的只是“您的应用程序崩溃了,因为您试图更改一个 NSDictionary 的键值对,它是不可变的而不是 NSMutableDictionary”ddddduuuuhhhhh
    【解决方案2】:

    今天我也遇到了这个问题,因为我正在像这样在字典中制作数据

    NSMutableDictionary *Dic =[myMutableAry objectAtIndex:0];  
    

    在我更新我的 dic 值时获取数据然后崩溃

    * 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:'-[__NSCFDictionary setObject:forKey:]: 变异方法发送到不可变对象'

    经过大量研究,我确实得到了解决方案,所以只做一件事

    NSMutableDictionary *Dic = [NSMutableDictionary dictionaryWithDictionary:[myMutableAry objectAtIndex:0]];
    

    【讨论】:

      【解决方案3】:

      你使用 NSUserDefaults 的方式是错误的,NSUserDefaults 返回一个不可变的字典。这就是这个问题的原因。因此,您必须从 NSUserDefaults 显式请求一个可变对象。请使用下面的代码行。

      NSMutableDictionary *configure = [[[NSUserDefaults standardUserDefaults] objectForKey:@"configure"]mutableCopy];
      

      这和我一起工作。 谢谢祝你好运:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-06
        • 1970-01-01
        • 2018-07-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多