我在NSMutableDictionary中有一个数组,我想向它添加对象。使用我当前的方法,我得到一个错误,说该数组是不可变的。
我认为问题出在我将字典保存到NSUserDefaults时。我正在检索它是NSDictionary
,但我同时创建了一个包含内容的新NSMutableDictionary
。
但是,数组似乎是不可变的。如何替换字典中的数组?
我的字典看起来像这样:
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:0], nil];
NSDictionary *dict = @{
@"firstKey": @{
@"theArray":array,
}
};
NSMutableDictionary *mutDict = [[NSMutableDictionary alloc] initWithDictionary:dict];
我正在尝试添加这样的对象:
[[[mutDict objectForKey:@"firstKey"] objectForKey:@"theArray"] addObject:[NSNumber numberWithInt:5]];
我可以在保存到mutDict
NSUserDefaults
内的数组中
从NSUserDefaults加载后,我尝试添加到字典中的数组时收到的错误消息:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'
答案 0 :(得分:1)
您可以直接将对象添加到数组中:
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:0], nil];
NSDictionary *dict = @{
@"firstKey": @{
@"theArray":array,
}
};
NSMutableDictionary *mutDict = [[NSMutableDictionary alloc] initWithDictionary:dict];
//Since Objective-C objects are always passed by reference (using pointers) you can add object to the array
[array addObject:[NSNumber numberWithInt:55]];
答案 1 :(得分:1)
以下是 const int edge = 16;
class MouseFilter : NativeWindow {
private Form form;
public MouseFilter(Form form, Control child) {
this.form = form;
this.AssignHandle(child.Handle);
}
protected override void WndProc(ref Message m) {
const int wmNcHitTest = 0x84;
const int htTransparent = -1;
if (m.Msg == wmNcHitTest) {
var pos = new Point(m.LParam.ToInt32());
if (pos.X < this.form.Left + edge ||
pos.Y < this.form.Top + edge||
pos.X > this.form.Right - edge ||
pos.Y > this.form.Bottom - edge) {
m.Result = new IntPtr(htTransparent);
return;
}
}
base.WndProc(ref m);
}
}
{NSOserDefaults上the documentation所说的内容:
特别注意事项
返回的字典及其内容是不可变的,即使您最初设置的值是可变的。
因此,当您从NSUserDefaults检索字典时,字典本身及其中的所有集合都是不可变的。你可以使顶级字典变得可变(我假设你正在做),但这不会传播到现在不可变的NSArrays中,这些NSArrays是字典中的值。
解决这个问题的唯一方法是浏览返回的字典,并用不可变的对应元素替换不可变的NSArrays。它可能看起来像这样。
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
subClassChildren(this.Controls);
}
private void subClassChildren(Control.ControlCollection ctls) {
foreach (Control ctl in ctls) {
var rc = this.RectangleToClient(this.RectangleToScreen(ctl.DisplayRectangle));
if (rc.Left < edge || rc.Right > this.ClientSize.Width - edge ||
rc.Top < edge || rc.Bottom > this.ClientSize.Height - edge) {
new MouseFilter(this, ctl);
}
subClassChildren(ctl.Controls);
}
}
说实话,虽然听起来你正在使用NSUserDefaults来做一些比它更复杂的事情。如果你想坚持复杂的数据结构,那么你应该研究类似Core Data的东西,或者如果看起来有点矫枉过正,请看看NSKeyedArchiver。
答案 2 :(得分:0)
将对象添加到数组中的快速示例,该数组是字典的一部分。
let arr = [0] // note that initial array may be immutable
var dict = ["fK": ["a":arr]] // even if "arr" will be mutable, but "dict" immutable
dict["fK"]!["a"]!.append(3) // this will not work. "dict" must be mutable
println(dict) //[fK: [a: [0, 3]]]
另一种方法
var arr = [0] // initial array must be mutable
var dict = ["fK": ["a":arr]] // in both cases dictionary must be mutable
arr.append(3)
let newArr = arr
dict["fK"]!["a"]! = newArr // because we change it's content
println(dict) //[fK: [a: [0, 3]]]