This question already has answers here:
Editing an NSMutableDictionary sub-dictionary
(2 answers)
Closed 8 years ago.
Fairly new to this. I am trying to add some value/keys to an array that already has value/keys.
The itemsArray contains the json and is derived from the variable json which is a parameter passed to the method from a rest api call.
This is the code I am using and it aborts (at [i setobject] with [__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
NSMutableDictionary *itemsArray = [json objectForKey:#"items"];
for ( NSMutableDictionary *i in itemsArray) {
[i setObject:#"FirstValue" forKey:#"parents"];
}
All this should do is add in the key called parents for each item in the dictionary.
Now if I hard code the value/keys to the mutable dictionary itemsArray - it works fine. Its just when I use the variable json which is passed as a parameter and obtained from a call to a rest api. So the issue is likely that itemsArray contains a immutable json object even though itemsArray is mutable.
The question I have is how do I make the json object mutable (assuming that will cure it) so it will work. ?
You have the answer right in the error message: itemsArray is a NSDictionary not an NSMutableDictionary. See the answer to What is an NSCFDictionary? for more details.
How did you create json? You need to make sure it contains an NSMutableDictionary for the key #"items".
You will need to create a mutable dictionary from your itemsArray. Something like:
NSMutableDictionary *mutableDictionary = [i mutableCopy];
You can then add objects to it as you'd like.
Related
I came across NSFrozenDictionary while debugging an app.
Shared index property declared as NSDictionary * sharedIndex = ...
What is it? How is it different from NSMutableDictionary?
It is an NSMutableDictionary marked as immutable.
One case to get __NSFrozenDictionaryM:
Have an array of mutable dictionaries:
NSArray *array = #[{NSMutableDictionary}, {NSMutableDictionary}, {NSMutableDictionary}]
Making a two-level-deep copy of it by:
NSArray *res = [[NSArray alloc] initWithArray:array copyItems:YES]
The resulting res array contains immutable copies of NSMutableDictionaries in array, which are of type __NSFrozenDictionaryM. I guess this is an optimisation to avoid really copying all dictionaries in the original array.
It is one of the concrete subclasses that is part of the NSDictionary class cluster.
There is a more academic description on Apple's documentation site.
Essentially: don't worry about it. If you declared it as a plain NSDictionary, then treat it as such: an immutable dictionary. Foundation may create something else under the hood for optimization purposes, but as far as your code is concerned, it's still an immutable dictionary.
This question already has answers here:
Immutable/Mutable Collections in Swift
(7 answers)
Closed 5 years ago.
I don't have any problem, i would just like some clarification on an issue regarding mutability.
In Objective-C we would use for example NSMutableArray to get a mutable array and an NSArray to get an immutable one. I don't know much about the inner workings of the two, but from what I can remember I believe that the difference is that NSArray only reserves an amount of memory specific to the initial value which makes it more efficient, while NSMutableArray has no idea how much memory it will require. Presumably this means that NSMutableArray has pointers to bits of memory that are all over the place and not one by one like with NSArray? Or does it perhaps just reserve a lot of memory hoping it won't run out?
In Swift the obvious substitution is let for immutable and var for mutable. If a variable is declared with these keywords that I see no difference between Swift and Objective-C. However, I don't understand how it works if I declare the variable without the var/let by, for example, storing it in another variable.
Let's say I have a dictionary such as [String: [String]]. In other words, for each string key there is an array of strings. Consider the following case:
var dictionary: [String: [String]] = [:]
dictionary["key"] = ["string0", "string1"]
//dictionary now is ["key": ["string0", "string1"]]
But what is the strings array now? Is it mutable because the dictionary is mutable? Is it mutable because everything we assign is mutable? How about the following case:
let dictionary = ["key": ["string0", "string1"]]
dictionary["key"].append("string2")
Would this work?
I guess the key issue is that in Objective-C I always define whether am I working with NSMutableArray or NSArray. Creating an array using the literal syntax [#"string"] always leads to an NSArray and it won't be mutable unless I specify it. In Swift I don't know when is what mutable.
Thanks
For arrays and dictionaries, the let or var keyword decides whether the whole collection would be mutable or immutable. In other words, if you declare a dictionary immutable by using the let keyword, you cannot change any of its values, so the second example would not work.
In Swift deciding whether a collection will be mutable or immutable only depends on the keyword you use to declare it, so declaring an array/dictionary using the let keyword will be equivalent to declaring an immutable array (NSArray in Objective-C) while declaring it with the var keyword will give you a mutable array (NSMutableArray in Objective-C).
If you create an array, a set, or a dictionary, and assign it to a
variable, the collection that is created will be mutable. This means
that you can change (or mutate) the collection after it is created by
adding, removing, or changing items in the collection. If you assign
an array, a set, or a dictionary to a constant, that collection is
immutable, and its size and contents cannot be changed.
So, let means constant, if you declare array or dictionary using let it will be immutable.
if you declare array or dictionary as var it will be mutable.
So, the case below will not work because dictionary will be immutable:
let dictionary = ["key": ["string0", "string1"]]
dictionary["key"].append("string2")
Check the reference here:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html
This question already has answers here:
What does a square-bracketed index after an NSArray mean? [duplicate]
(2 answers)
Closed 9 years ago.
What is the term or name of the operation for getting member of an array? For example, this method returns a simple array:
- (NSArray*)createArray
{
NSArray *myArray = [[NSArray alloc] initWithObjects:#"unordentliches array", #"beliebiges Value", nil];
return myArray;
}
And I can NSLog one of its elements in the following way:
NSLog(#"%#", [self createArray][1]);
Output:
beliebiges Value
Good, no problem here.
But what do we call this operation: [self createArray][1]? One that allows us to -- without first assigning the value to a NSString -- simply put this [1] right next to the the returned value from a method call and output the value?
[self createArray][1];
What is the technical term for this?
Putting the element index in parentheses (or brackets in this case) after an array is called “subscripting”. The index is called a “subscript”.
There is no special name for directly subscripting the array returned by a message without storing the array in a variable first.
Under the covers, the compiler turns the subscripting into another message, like this:
[[self createArray] objectAtIndexedSubscript:1];
Sending a message directly to the object returned by another message is called “message chaining” or “method chaining”.
I have a very simple HTTP query that runs and grabs some JSON object in another class. I have an NSDictionary object called finalDataArray being defined. I am basically trying to loop through and append names to a table, the number of rows are being calculated correctly. finalDataArray.count
But when I try to do this, I get an error on the first line below.
NSArray *contactArray = [finalDataArray allKeys];
NSLog(#"%#", contactArray);
Because I am such a newb, I didn't realize that if you had a "Miltidimensional" JSON object... it should be NSDictionary, but if you have a single dimenstional object... it should be NSArray which fixes my issue...
Thanks for all the help.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Syntax help - Variable as object name
I have a very basic beginner's question in Objective C:
I'd like to declare a variable that is named after the content/value/literal of another variable. How can I do that?
I.e.
NSString *s = [NSString stringWithFormat:#"variableName"];
// now create a second variable that is named after the literal in s
int *s = 42; // This is what doesn't work. The integer-type variable should be named variableName
Does anyone know how to do this?
Thanks for the answers so far. The reason why I am asking this questions is the following:
I have an array containing values I load from an xml file structured as follows:
<string>name</string><integer>23</integer><real>3.232</real><real>4.556</real> ... (44 times another real number)<string>nextName</string>...(and so on).
The file contains the names for MKPolygons, the number of points for each polygon and the latitude and logitude values for each point of the polygon. I managed to load the file and have its content in an array. Now I want to create MKPolygons from this array which are named as the strings in the array.
What you are looking for is a hash table. You can use NSDictionary or NSMutableDictionary or NSHashTable.
Here is an example:
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:anObj forKey:#"foo"];
[dict objectForKey:#"foo"];
[dict removeObjectForKey:#"foo"];
[dict release];
This is not possible in Objective-C, nor in most mainstream languages (save for PHP). What are you trying to accomplish with this?
I don't think you can do it. However, you can create an NSDictionary and create a key called variableName and a value called 42. (an NSNumber). Then whenever you want to retrieve this value, you can just do valueForKey.