NSMutableDictionary 中的更改未反映在父 NSDictionary 中

Posted

技术标签:

【中文标题】NSMutableDictionary 中的更改未反映在父 NSDictionary 中【英文标题】:Changes in NSMutableDictionary not reflecting in parent NSDictionary 【发布时间】:2017-08-02 21:31:22 【问题描述】:

问题 1)

我正在使用以下代码从 NSDictionary 创建 NSMutableDictionary:

_allKeysDictionary = [receivedDictionary mutableCopy];

我正在使用以下代码更新 _allKeysDictionary 中的值:

[_allKeysDictionary setObject:[textField text] forKey:@"field"];

但我的父母 NSDictionaryreceivedDictionary 并未反映 _allKeysDictionary 中所做的更改。

我需要更新receivedDictionary 的值。


问题 2)

我正在使用

(__bridge CFMutableDictionaryRef)

在我的 JSON 响应中保留指向 NSDictionary 之一的指针。但是当我试图重新获得上述CFMutableDictionaryRef 时,我仍然得到NSDictionary。我不知道出了什么问题。我正在使用以下代码从参考中重新获得字典

NSMutableDictionary *getPointedDict = (__bridge NSMutableDictionary*) dataRefValue;

【问题讨论】:

【参考方案1】:

Q1: 但是mutableCopy 方法甚至这么说:创建了一个副本! receivedDictionary 逻辑上不会改变。

更新(完成后):

receivedDictionary = _allKeysDictionary;

或者为了安全起见,以后不能进行任何更改:

receivedDictionary = [NSDictionary dictionaryWithDictionary: _allKeysDictionary];

顺便说一句,你可以写:

_allKeysDictionary[@"field"] = textField.text;

Q2:在 Obj-C(和许多其他语言)中,强制转换不会改变对象的结构。如果是NSDictionary,它将始终保持为NSDictionary。所以实际的转换会起作用(即编译器不会告诉你),但是一旦你开始对原始类中没有实现的对象做一些事情,你的应用程序就会崩溃或者你会得到其他未定义的结果。

【讨论】:

【参考方案2】:

但我的父母 NSDictionaryreceivedDictionary 并未反映在 _allKeysDictionary 中所做的更改

当然不是,您制作了mutableCopy - 这是一个副本。您现在有两个具有相同键和值的字典。

我需要更新receivedDictionary 的值

如果是NSDictionary,你不能这样做,这就是不可变的意思。您可以receivedDictionary 中存储的引用替换为引用您的新可变字典(或它的不可变副本)的引用,但这并不能满足您希望其他变量存储引用原来的字典。

但是,如果字典中的值本身是可变的,那么您可以更改这些值。例如。如果你 NSDictionary 包含 NSMutableArray 值,那么你可以更改这些数组的元素,但你不能更改哪个数组与字典中的哪个键相关联。

Q2:您不能简单地将对不可变字典的引用转换为可变字典。无论如何,强制转换不会更改引用的对象,它只会更改编译器将其视为的类型(如果该类型与您的程序中断的实际类型不兼容)。

您似乎对对象、引用和可变性不确定;可能是时候做一些研究了。

HTH

【讨论】:

当然。我同意你的最后一点,我会更深入地研究。但只是一个快速的问题。如果我的父字典是可变的,那么其中的所有数组和字典默认都是可变的?? 没有。可变性适用于字典本身,而不是它的值。如果您添加一个可变数组/字典,那么它仍然是可变的,但添加它不会使其可变。 好的.. 明白了。谢谢!【参考方案3】:
    MutableCopy 和复制都在 NSDictionary 上进行深度复制。唯一的区别是 mutableCopy 使您的新 dict 可变。 当您进行深度复制时,您复制的是值,而不是引用,这意味着无论您在新字典上做什么,都不会影响旧值。 另外,您的原始字典是不可变的,即使您复制引用,它的值也不会改变。

【讨论】:

抱歉,副本深,仅复制存储在字典中的引用。 不。这称为一层深拷贝。字典本身是深度复制的。它的内容是浅拷贝的。 抱歉,不,请参阅 this、this 和 this。 “一层深拷贝”(OLDC)作为一个定义的概念被证明是很难找到的。 This 是 Ruby 中的一种用法,其中 clone(相当于 Obj-C copy,浅拷贝)不足以完成任务,并且编写了自定义 OLDC - 克隆对象 + 克隆它的引用对象。 但是新字典的内存地址与之前的字典不同,对吧?如果是纯浅拷贝,即使是新字典也应该和前一个字典有相同的地址(指针)。 来自第一个链接“复制对象的一种方法是浅拷贝。在这种情况下,会创建一个新对象 B,并将 A 的字段值复制到 B。”

以上是关于NSMutableDictionary 中的更改未反映在父 NSDictionary 中的主要内容,如果未能解决你的问题,请参考以下文章

在从 NSMutableDictionary 加载的 textview 中保存更改的文本

从一个类访问和更改 NSMutableDictionary 的值到另一个 iOS

在 UITableView 中过滤 NSMutableDictionary 数据

如何更改 NSMutableDictionary int 值

每次在 plist 中添加新的 NSMutableDictionary,即使我只分配一次

NSMutableArray 未更新且 UITableView 未重新加载