xcode '-[__NSCFDictionary setObject:forKey:]:发送到不可变对象的变异方法'
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12390159/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
'-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
提问by Thromordyn
- (NSMutableDictionary *)updateTemplates:(NSMutableDictionary *)oldTemplates
forSpecType:(NSString *)specType {
// oldTemplates is an NSMutableDictionary pulled from a plist
// specType is used for flexible paths, to eliminate duplicate code
// Make a dict of the parameters object (about to be overwritten)
NSMutableDictionary *parameters = [oldTemplates valueForKeyPath:
[NSString stringWithFormat:@"root.%@.parameters", specType]];
// Dump the new data into the matching object
[oldTemplates setValue:[updateTemplates valueForKeyPath:
[NSString stringWithFormat:@"data.%@", specType]]
forKeyPath:[NSString stringWithFormat:@"root.%@", specType]];
// Put the parameters back, since they don't exist anymore
/* Instant crash, with the debugger claiming something is immutable
* But I just used the exact same method on the line above
* updateTemplates isn't immutable either; it's only when I try to mutate
oldTemplates after putting in updateTemplates -- and only the update
seems to be breaking things -- that I get the exception and crash
*/
[oldTemplates setValue:parameters forKeyPath:
[NSString stringWithFormat:@"root.%@.parameters", specType]];
return oldTemplates;
}
I could set up a loop to write one object of updateTemplates.specType
at a time so only those parts get replaced and then I don't have to do anything with the parameters, but if it's immutable now, it will be when I try to write to it again. That won't do me any good.
我可以设置一个循环来一次写入一个对象,updateTemplates.specType
这样只有那些部分被替换,然后我不必对参数做任何事情,但如果它现在是不可变的,那么当我尝试写入它时再次。那对我没有任何好处。
回答by Snowman
If I remember correctly, dictionaries created from plists or NSUserDefaults are immutable by default. You'll have to create a mutable copy manually:
如果我没记错的话,默认情况下,从 plists 或 NSUserDefaults 创建的字典是不可变的。您必须手动创建一个可变副本:
NSMutableDictionary *parameters = [[oldTemplates valueForKeyPath:
[NSString stringWithFormat:@"root.%@.parameters", specType]] mutableCopy];
回答by bbum
mutableCopy
makes a shallow mutable copy, not a deep mutable copy. If you have an NSDictionary
containing key/value pairs where the values are NSDictionary
instances, mutableCopy
will return a mutable dictionary containing those NSDictionary
immutable instances as values.
mutableCopy
制作浅可变副本,而不是深可变副本。如果您有一个NSDictionary
包含键/值对,其中值是NSDictionary
实例,mutableCopy
将返回一个包含这些NSDictionary
不可变实例作为值的可变字典。
You either need to do a deep copy or use the plist serialization functionality to decode the plist with the mutable collections option enabled. Or you could compose a new collection derived from the old.
您要么需要进行深度复制,要么使用 plist 序列化功能在启用可变集合选项的情况下解码 plist。或者你可以从旧的集合中创建一个新的集合。
回答by jere
You can simply do:
你可以简单地做:
NSMutableDictionary* oldTemplates = [NSMutableDictionary dictionaryWithDictionary:[oldTemplates valueForKeyPath:
[NSString stringWithFormat:@"root.%@.parameters", specType]]];
This will create a mutable copy from an existing NSDictionary
这将从现有的 NSDictionary 创建一个可变副本