0

Question 1)

I am creating a NSMutableDictionary from a NSDictionary using the following code:

_allKeysDictionary = [receivedDictionary mutableCopy];

and I am updating the values from the _allKeysDictionary using the following code:

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

But my parent NSDictionary that is receivedDictionary is not reflecting those changes made in _allKeysDictionary.

I need the values of receivedDictionary to be updated.


Question 2)

I am using

(__bridge CFMutableDictionaryRef)

to keep a pointer to one of the NSDictionary in my JSON response. but when I am trying to regain the above CFMutableDictionaryRef, I am still getting NSDictionary. I don't know what is wrong. I am using the following code to regain the Dictionary from the reference

NSMutableDictionary *getPointedDict = (__bridge NSMutableDictionary*) dataRefValue;
halfer
  • 19,824
  • 17
  • 99
  • 186
AabidMulani
  • 2,325
  • 1
  • 28
  • 47

3 Answers3

2

Q1: But the method mutableCopy even says so: A copy is created! The receivedDictionary logically won't be changed.

To update (after you're done):

receivedDictionary = _allKeysDictionary;

or to be safe that no changes can be made later:

receivedDictionary = [NSDictionary dictionaryWithDictionary: _allKeysDictionary];

By the way, you can write:

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

Q2: In Obj-C (and many other languages) casting does not change the structure of the object. If it's an NSDictionary, it will always stay an NSDictionary. So the actual cast will work (i.e. the compiler won't tell you), but once you start doing things with the object that are not implemented in the original class, your app will crash or you'll get other undefined results.

meaning-matters
  • 21,929
  • 10
  • 82
  • 142
0

But my parent NSDictionary that is receivedDictionary is not reflecting those changes made in _allKeysDictionary

Of course they are not, you made a mutableCopy - that is a copy. You've now got two dictionaries with the same keys and values.

I need the values of receivedDictionary to be updated

If it is an NSDictionary you cannot do this, that is what immutable means. You can replace the reference stored in receivedDictionary to one which references your new mutable dictionary (or an immutable copy of it), but that doesn't do what you wish you have other variables storing references to the original dictionary.

However if the values in the dictionary are themselves mutable then you can alter those values. E.g. if you NSDictionary contains NSMutableArray values then you can change the elements of those arrays, but you cannot change which array is associated with which key in the dictionary.

Q2: You cannot simply cast a reference to an immutable dictionary to make it into a mutable one. Casting doesn't change the referenced object in anyway, it just changes the type the compiler treats it as (and if the type is not compatible with the actual type your program breaks).

It looks like you are unsure about objects, references and mutability; probably time to do some studying.

HTH

CRD
  • 52,522
  • 5
  • 70
  • 86
  • Sure. I agree to your last point and I will study more deeply. But just a quick question. If my parent Dictionary is mutable, then all the Arrays and Dictionaries in it will be Mutable by default?? – AabidMulani Aug 02 '17 at 21:50
  • No. Mutability applies to the dictionary itself, not its values. If you add a mutable array/dictionary then it remains mutable, but adding it doesn't make it mutable. – CRD Aug 02 '17 at 21:51
  • Okay.. got it. Thanks! – AabidMulani Aug 02 '17 at 21:51
0
  1. MutableCopy & copy both do deep copy on NSDictionary. The only difference is that mutableCopy makes your new dict mutable.
  2. When you do deep copy, you are copying the value, not the reference, which mean whatever thing you do on your new dictionary, it won't affect the old value.
  3. Plus, your original dict is immutable, even if you copy the reference, its value won't change.
Developer Sheldon
  • 2,140
  • 1
  • 11
  • 17
  • Sorry, but copies are *not* deep, only the references stored in the dictionary are copied. – CRD Aug 03 '17 at 00:38
  • Nope. This is called one layer deep copy. The dictionary itself is deep copied. It's content is shallow copied. – Developer Sheldon Aug 03 '17 at 13:42
  • Sorry, no, see [this](https://en.m.wikipedia.org/wiki/Object_copying), [this](https://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy), and [this](https://www.codeproject.com/articles/28952/shallow-copy-vs-deep-copy-in-net). "One layer deep copy" (OLDC) proved hard to find as a defined concept. [This](https://github.com/avdi/prototypes-in-ruby/blob/master/prototypes.org) is a use in Ruby where `clone` (equiv of Obj-C `copy`, shallow copy) is insufficient to the task and a custom OLDC is written - clone object + clone it's referenced objects. – CRD Aug 03 '17 at 17:12
  • But the new dict is having a different memory address other than the previous dictionary, right? If it is pure shallow copy, even the new dictionary should have same address (pointer) as the previous one. – Developer Sheldon Aug 03 '17 at 19:03
  • From the first link "One method of copying an object is the shallow copy. In that case a new object B is created, and the fields values of A are copied over to B." – CRD Aug 03 '17 at 20:12
  • so only using NSArchiver and UnArachiver will do deep copy? – Developer Sheldon Aug 04 '17 at 18:14
  • Provided *all* objects in your collection (i.e. the objects in the dictionary, objects those objects reference, etc.) then archiving + unarchiving can be used to do a deep copy. – CRD Aug 04 '17 at 19:10