将对象添加到从NSUserDefaults加载的NSMutableDictionary中的数组

时间:2015-07-11 10:17:06

标签: ios objective-c nsarray nsdictionary nsuserdefaults

我在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'

3 个答案:

答案 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]]]