Objective C. NSMutable Dictionary adding value to existing key - objective-c

Is there any way to add a value to an existing key on a NSMutableDictionary?
Here is snippet of my code
NSMutableArray *mainFeedList = [NSMutableArray array];
[mainFeedList addObjectsFromArray:feedList];
for(int i = 0; i < mainFeedList.count; i++){
NSMutableArray *allFeed = [NSMutableArray array];
NSString *categoryId = [mainFeedList[i] valueForKey: #"categoryId"];
[allFeed addObject:mainFeedList[i]];
if(allFeed != nil && allFeed.count > 0) {
[feedContent setObject:allFeed
forKey:[combinedCategories[(int)[categoryId integerValue]] valueForKey: #"name"]];
}
Sample scenario:
NSMutableDictionary *mDict = #{#"key1":#"value1",#"key2": #"value2"};
I know that
[mDict setObject:mArray forKey:#"key1"];
will set an object to key1 but what I need is
add another object to key1 without replacing existing object (i need it both)

A structure of any NSDictionary is "one key to one object". If you would like to build a structure which maps one key multiple objects, you need an NSDictionary that maps keys to collections, such as NSArray or NSMutableArray:
NSMutableDictionary *mDict = #{
#"key1": [#[ #"value1" ] mutableCopy]
, #"key2": [#[ #"value2" ] mutableCopy]
};
Now you can add values to keys without replacing the existing ones:
[mDict[#"key1"] addObject:#"value3"];

NSDictionary only allows a single object corresponding to a single key. If you would like to add multiple objects corresponding to a single key, if you have string type of object then you can use separators also to combine strings like:
[mDict setObject:[NSString stringWithFormat:#"%#,%#", [mDict objectforKey:#"key1"], #"value2"] forKey:#"key1"];
Otherwise, you have to take collections, which you have already defined in your question.

add another object to key1 without replacing existing object...
why not set an dict to key1?
before:
[dict setObject:#"a" forKey:#"key1"];
U wanna:
add #"b" to "key1", in dict;
why not like:
[dict setObject:#{#"a":#"subKey1", #"b":#"subKey2"} forKey:#"key1"];

I would suggest storing an array as a key in your dictionary like I do below :
// Setting the value for "key1" to an array holding your first value
NSMutableDictionary *mDict = #{#"key1":#["value1"],#"key2": #"value2"};
Now when I want to add a new value I would do this:
// Create temp array
NSMutableArray *temp = mDict[#"key1"];
// Add new object
[temp addObject:#"value3"];
// Convert temp NSMutableArray to an NSArray so you can store it in your dict
NSArray *newArray = [[NSArray alloc] initWithArray:temp];
// Replace old array stored in dict with new array
mDict[#"key1"] = newArray;
Furthermore, if you are not sure if an array is already stored for that key you can run a check and populate with an empty dictionary like below:
if (mDict[#"key1"] == nil) {
mDict[#"key1"] = #[];
}

Related

How to remove elements of NSDictionary

I have NSArray of NSDictionaries I need to extract 2 values or remove the values I don't need from the dictionary in the example below I need to remove id and NumberValue. any of you knows how can I do that?
Array: (
{
customerUS= {
DisplayName = "level";
InternalName = "Number 2";
NumberValue = 1;
id = xwrf
},
customerCAN= {
DisplayName = "PurchaseAmount";
InternalName = "Number 1";
NumberValue = 3500;
id = adf;
};
}
)
I'll really appreciate your help.
First thing, You can not remove/insert/update value in (immutable) NSDictionary/NSArray you need to convert NSDictionary/NSArray to (mutable) NSMutableDictionary/NSMutableArray.
such like
NSArray *myArr = ....;
NSMutableArray *newMutableArr = [myArr mutableCopy];
Then you can change in newMutableArr.
Such like
for(int i = 0 ; i < newMutableArr.count ; i ++)
{
[[newMutableArr objectAtIndex:i] removeObjectForKey:#"id"];
[[newMutableArr objectAtIndex:i] removeObjectForKey:#"NumberValue"];
}
EDITED:
Without Use of for loop and removeObjectForKey, if you have array of dictionary and both are mutable then you can also delete a key and its object from all elements of the array like this:
[newMutableArr makeObjectsPerformSelector:#selector(removeObjectForKey:) withObject:#"id"];
[newMutableArr makeObjectsPerformSelector:#selector(removeObjectForKey:) withObject:#"NumberValue"];
I would advice you to read Apple documents.
For modifying any Collection object after it is created, you need the mutable version.
For NSDictionary we have NSMutableDictionary. Read here.
We have a method for removing objects:
- (void)removeObjectForKey:(id)aKey
There are other methods as well. You can easily refer them in the above mentioned documentation.
Find out removeObjectForKey for deleting record from NSMutabledictionary.
removeObjectForKey pass the key value whatever you have like
all this are your key
DisplayName,
InternalName,
NumberValue,
id
do like this
removeObjectForKey:#"id";
First of all you have to convert the array to mutable array and then you can remove the key-value pairs from dictionary.
NSMutableArray *mutableArray = [yourArray mutableCopy];for(int i=0;i<mutableArray.count;i++){ NSMutableDictionary *outerDictionary = [mutableArray objectAtIndex:i]; for(NSString *key in outerDictionary.allKeys){ NSMutableDictionary *innerDictionary = [outerDictionary objectForKey:key]; [innerDictionary removeObjectForKey:#"id"]; [innerDictionary removeObjectForKey:#"NumberValue"]; }
}

NSArray of NSDictionaries - filtering by dictionary value and return unique array object

So suppose I have an NSArray populated with hundreds of NSDictionary objects.
All dictionary objects have a value for the key name but these values names may appear more than once in different objects.
I need to be able to filter this NSArray to only return one object per unique name attribute (whichever object, first or last, I don't care).
This is how far I've got but obviously my filtered array contains all objects rather than only unique ones.
I'm thinking there must be a way to tell the predicate to limit its results to only one / first match?
NSArray *allObjects = ... // This is my array of NSDictionaries
NSArray *uniqueNames = [allObjects valueForKeyPath:#"#distinctUnionOfObjects.name"];
NSArray *filtered = [allObjects filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"(self.name IN %#)", uniqueNames]];
Thanks!
NSMutableDictionary *uniqueObjects = [NSMutableDictionary dictionaryWithCapacity:allObjects.count];
for (NSDictionary *object in allObjects) {
[uniqueObjects setObject:object forKey:object[#"name"]];
}

Create Instance variables at runtime

I want to create instance variables dynamically at runtime, and I want to add these variables to a category. The number of the instance variables may change based on the configuration/properties file which I am using for defining them.
Any ideas??
Use Associative References - this is tricky, but that is the mechanism invented specifically for your use case.
Here is an example from the link above: first, you define a reference and add it to your object using objc_setAssociatedObject; then you can retrieve the value back by calling objc_getAssociatedObject.
static char overviewKey;
NSArray *array = [[NSArray alloc] initWithObjects:# "One", #"Two", #"Three", nil];
NSString *overview = [[NSString alloc] initWithFormat:#"%#", #"First three numbers"];
objc_setAssociatedObject (
array,
&overviewKey,
overview,
OBJC_ASSOCIATION_RETAIN
);
[overview release];
NSString *associatedObject = (NSString *) objc_getAssociatedObject (array, &overviewKey);
NSLog(#"associatedObject: %#", associatedObject);
objc_setAssociatedObject (
array,
&overviewKey,
nil,
OBJC_ASSOCIATION_ASSIGN
);
[array release];
I'd be inclined to just use a NSMutableDictionary (see NSMutableDictionary Class Reference). Thus, you would have an ivar:
NSMutableDictionary *dictionary;
You'd then initialize it:
dictionary = [NSMutableDictionary dictionary];
You can then save values to it dynamically in code, e.g.:
dictionary[#"name"] = #"Rob";
dictionary[#"age"] = #29;
// etc.
Or, if you are reading from a file and don't know what the names of the keys are going to be, you can do this programmatically, e.g.:
NSString *key = ... // your app will read the name of the field from the text file
id value = ... // your app will read the value of the field from the text file
dictionary[key] = value; // this saves that value for that key in the dictionary
And if you're using an older version of Xcode (before 4.5), the syntax is:
[dictionary setObject:value forKey:key];
Depends on exactly what you want to do, the question is vague but if you want to have several objects or several integers or so on, arrays are the way to go. Say you have a plist with a list of 100 numbers. You can do something sort of like this:
NSArray * array = [NSArray arrayWithContentsOfFile:filePath];
// filePath is the path to the plist file with all of the numbers stored in it as an array
That will give you an array of NSNumbers, you can then turn that into an array of just ints if you want like this;
int intArray [[array count]];
for (int i = 0; i < [array count]; i++) {
intArray[i] = [((NSNumber *)[array objectAtIndex:i]) intValue];
}
Whenever you want to get an integer from a certain position, lets say you want to look at the 5th integer, you would do this:
int myNewInt = intArray[4];
// intArray[0] is the first position so [4] would be the fifth
Just look into using a plist for pulling data, it will them be really easy to create arrays of custom objects or variables in your code by parsing the plist.

How do I append an object to NSMutableArray?

I want to update an mutable array. i have one array "ListArray" with some keys like "desc", "title" on other side (with click of button.) i have one array name newListArray which is coming from web service and has different data but has same keys like "desc" "title". so i want to add that data in "ListArray" . not want to replace data just add data on same keys. so that i can show that in tableview.
..........So my question is how to add data in "ListArray". or any other way to show that data in tableview but replacing old one just want to update the data
NSMutableArray *newListArray = (NSMutableArray*)[[WebServices sharedInstance] getVideoList:[PlacesDetails sharedInstance].userId tokenValue:[PlacesDetails sharedInstance].tokenID mediaIdMin:[PlacesDetails sharedInstance].minId mediaIdMax:[PlacesDetails sharedInstance].maxId viewPubPri:#"Public_click"];
NSDictionary *getNewListDic = [[NSDictionary alloc] initWithObjectsAndKeys:newListArray,#"videoList", nil];
[listVidArray addObject:getNewListDic];
NSArray *keys = [NSArray arrayWithObjects:#"desc",#"url",#"media_id",#"img",#"status",#"media_id_max",#"fb_url",#"title", nil] ;
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
for(int i = 0 ; i < [listVidArray count] ; i++)
{
for( id theKey in keys)
{
// NSMutableArray *item = [NSMutableArray array];
NSLog(#"%#",theKey);
NSLog(#"%#",keys);
[dict setObject:[[[listVidArray objectAtIndex:i]valueForKey:#"videoList"] valueForKey:theKey] forKey:theKey];
// [dict setObject:[newListArray valueForKey:theKey] forKey:theKey];
}
}
If you the newListArray is totally different from the oldListArray, then clear the old one, and use the new data to fit it.
Otherwise, you need to merge the two arrays. One way is to check if a
data in newListArray is/is not in oldListArray and then decide
whether to add it into oldListArray.
When oldListArray is updated, call -reloadData of the tableView.
If I do not misunderstand your question, you may do something like this:
[listArray addObjectsFromArray:newListArray];
[_tableView reloadData];

NSMutableDictionary, alloc, init and reiniting

In the following code:
//anArray is a Array of Dictionary with 5 objs.
//here we init with the first
NSMutableDictionary *anMutableDict = [[NSMutableDictionary alloc] initWithDictionary:[anArray objectAtIndex:0]];
... use of anMutableDict ...
//then want to clear the MutableDict and assign the other dicts that was in the array of dicts
for (int i=1;i<5;i++) {
[anMutableDict removeAllObjects];
[anMutableDict initWithDictionary:[anArray objectAtIndex:i]];
}
Why this crash? How is the right way to clear an nsmutabledict and the assign a new dict?
Thanks guy's.
Marcos.
You do not "reinit" objects — ever. Initialization is meant to be used on a newly alloced instance and might make assumptions that aren't true after initialization is complete. In the case of NSMutableDictionary, you can use setDictionary: to completely replace the contents of the dictionary with a new dictionary or addEntriesFromDictionary: to add the entries from another dictionary (without getting rid of the current entries unless there are conflicts).
More generally, you could just release that dictionary and make a mutableCopy of the dictionary in the array.
If you use an autoreleased dictionary, your code will be a lot simpler:
NSMutableDictionary *anMutableDict = [NSMutableDictionary dictionaryWithDictionary:[anArray objectAtIndex:0]];
... use of anMutableDict ...
for (int i=1; i<5; i++)
{
anMutableDict = [NSMutableDictionary dictionaryWithDictionary:[anArray objectAtIndex:i]];
}
But I don't see the point of that loop you have at the end there.
This isn't how you use init/alloc. Instead, try:
//anArray is a Array of Dictionary with 5 objs.
//here we init with the first
NSMutableDictionary *anMutableDict = [[NSMutableDictionary alloc] initWithDictionary:[anArray objectAtIndex:0]];
... use of anMutableDict ...
//then want to clear the MutableDict and assign the other dicts that was in the array of dicts
for (int i=1;i<5;i++) {
[anMutableDict removeAllObjects];
[anMutableDict addEntriesFromDictionary:[anArray objectAtIndex:i]];
}