Replace some contents of NSMutableDictionary with another NSMutableDictionary - ios

i am having 2 NSMutableDictionaries that each has 5 NSArrays inside,
these 2 NSMutableDictionaries have excactly the same 5 keys and NSArrays but with different content,
i need to replace only 2 Arrays with the Arrays of the other NSMutableDictionary
so
dic1 = dic2; //isn't a solution...will replace all the contents of the one to the other...
i need something that can replace the object of a specific key with the other same key.
i tried
[dic1 setObject:[dic2 objectForKey:#"key1"] forKey:#"key1"];
[dic1 setObject:[dic2 objectForKey:#"key2"] forKey:#"key2"];
and i get ERROR: attempt to insert nil value (key: key1)'

The error just means [dic2 objectForKey:#"key1"] is returning a nil value. In other words, that key does not exist in the dictionary. Likewise, you can't set a nil value inside of an NSDictionary, so thats why the error is sent out.
Print out each of the dictionaries and ensure your keys/values are what you expect. You can use an NSLog or just pause the program with a breakpoint, and enter po dic1 in the console.

Related

Passing Null Values and a variable in to NSMutableArray/NSArray. Why is there a difference in output?

My question is how to pass Null values in to NSMutableArray/NSArray.
But by searching google and going through different sites, i think that i have achieved my purpose. But, while trying i got a new doubt.
See the below code to understand my question
I am declaring a mutable array and initializing it with some objects initially and also i am passing a null in to it at the time of declaration itself.
Now when i run this code below
NSMutableArray * mar = [[NSMutableArray alloc]initWithObjects:#"first",#"last", nil];
[ar addObject:[NSNull null]];
NSLog(#"%#",mar);
The o/p is :
(
first,
last,
"<null>"
)
But my actual doubt is when i initialize the NSMutableArray as below
NSString *str;
NSMutableArray * mar = [[NSMutableArray alloc]initWithObjects:#"first",str,#"last", nil];
[ar addObject:[NSNull null]];
NSLog(#"%#",mar);
The o/p is :
(
first,
"<null>"
)
The 2nd element in the array is "null", i understand that as i have passed a variable without assigning any value to it. It is printing null. But why are the remaining elements not printed.
According to what i know, the array will stop adding elements whenever it overcomes nil while initializing. But here, in this case. The o/p shows that the 2nd element is also null.(But not nil.)
Then why does the remaining elements are not printed.
UPDATING QUESTION
NSString* str;
NSLog(#"%#",str);
NSMutableArray * mar = [[NSMutableArray alloc]initWithObjects:#"first",str,#"last", nil];
NSLog(#"%#",mar);
and the o/p for the above code is
(null) // for str an uninitialised NSString variable.
(
first // first element in the array
)
If the value present in str is (null), how come the array encountered nil and stopped adding elements to array and printing them.
Now, someone answer this?
initWithObjects uses nil as the marker for the last item. If you pass a nil (the unitialized str variable) to it as the 2nd item out of 4, only the first one is actually added.
[[NSMutableArray alloc]initWithObjects:#"first",str ?: [NSNull null],#"last", nil];
will fix your problem by replacing the nil with a [NSNull null].
Also see NSArray creation with variable argument lists
in objective-C, when iterating through Array if nil/null encountered then it gets treated as end of array.
this is the reason it is not printing remaining values.
in case you want clear diff between nil/null/Nil then check Difference between nil, NIL and, null in Objective-C

NSMutableArray Extra Nil Sentinels

I've read a text file into an array of strings. In the below code I'm creating objects from that array and adding them into an NSMutableArray.
NSMutableArray* metaphors = [[NSMutableArray alloc] init];
unsigned int i, cnt = [allLinedStrings count];
for(i = 0; i < cnt-3; i+=5)
{
Metaphor *newMetaphor = [[Metaphor alloc] init];
[newMetaphor setMetaphorTitle: allLinedStrings[i]];
[newMetaphor setCorrectAnswer: allLinedStrings[i+1]];
[newMetaphor setLiteralAnswer: allLinedStrings[i+2]];
[newMetaphor setWayOffAnswer: allLinedStrings[i+3]];
[metaphors addObject:newMetaphor];
}
As for the problem, when I access any item via index ([metaphors objectAtIndex:3] for example) every other element (odd numbered ones) are nil elements. All of the objects are added to the array, though. My guess is that addObject is adding an element to the array as well as a new nil sentinel every time? Should this be happening/should I manually go through and remove these elements?
Also a side note, as I'm new to Objective-C, my Metaphor class contains the 4 instance fields you can see within the body: I'm sure there is quicker syntax to initialize one of these objects if anyone could point me the right way. Thanks.
NSArray can't contain nil. It's invalid. If you are getting nil back in a call to an array, the array pointer itself is almost certainly nil. (You CAN send messages to a nil object pointer in Objective C. It simply returns nil/zero.)
Trying to add a nil to an NSArray will cause a crash, and trying to index past the end of an NSArray will also crash.
There is a special class NSNull that provides a singleton placeholder object that can take the place of a nil entry in an NSArray.
The nil sentinel is only a way to know the last element of a variable length array has been reached. The nil sentinel ISN'T added to the NSMutableArray;
NSMutableArray addObject method doesn't need a nil sentinel as you only add ONE object, not a variable length array.
If you need to add something "nil" to an array, you might use [NSNull null] which is an object "equivalent to nil".

Saving IOS dictionary with arrays as keys

i am working with Tapku's Calendar, and i want to save some values that will be user inputed.
But i am kind of stumbled on how i would achive this, here is the layout:
// allocate the arrays and dictionary
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
NSMutableArray *dateValueArray = [[NSMutableArray alloc] init];
// set array values
[dateValueArray addObject:#"first string"];
[dateValueArray addObject:#"Second string"];
// set dictionary with date as key, and array as value
[dict setObject:dateValueArray forKey:testdate];
The dictionary dict, will be the only Dictionary, but since that dictionary uses arrays for objects, i would have multiple arrays.
So, lets say there are multiple dates registerd in "dict", different keys would have to use different arrays? Sorry i am abit confused my self here.
Is there any way i can use 1 array to store all the strings associated with different dictionary keys ?
EDIT 1
Elaboration:
The whole idea is that the user can input text that are associated with dates.
I will need to store these values and i will need to store which date they are associated to.
So i have multiple values in an array, associated with 1 date in a dictionary.
And keeping in mind that i will have to store this, i would like to know how i should assign the values to the dates.
EDIT 2:
Basically what i need for the Array is something like AddObject ForKey
Edit 3
More elaboration::
Basically i want to access the values in this manner:
[date1][note1]
[date1][note2]
[date2][note1]
[date2][note2]
And the amount of values in both date and note are variable.
If I understand what you are asking about, what you want is the property of NSDictionary allKeys which is an array of all the keys in that dictionary.
Now I see your edit. You are in the right way. To perform what you are looking for, do something like this:
First, allocate your dict somewhre:
// allocate the arrays and dictionary
NSMutableDictionary *dict = [NSMutableDictionary new];
Now, everytime you get a new date with a new string, first check if there's the first string for that date. If yes, create a new array. If not, add your string inside the previously array.
NSMutableArray *valuesForDate = dict[givenDate];
if (!valuesForDate)
{
valuesForDate [NSMutableArray new];
dict[givenDate] = valuesForDate
}
[valuesForDate addObject:#"first string for dateGiven"];
[valuesForDate addObject:#"Second string for dateGiven"];
Now you can retrieve the values with something like you wanted:
NSString *test = dict[date1][0]; //first string associated for date1
NArray *allStringsForDate2 = dict[date2]; //array with all the strings for date2
You can try using NSMapTable instead of NSDictionary, which is much more flexible but also much harder to use. You'll also find it hard to find anyone knowing the answers if you have questions about NSMapTable. But you can definitely create an NSMapTable which will use pointers of objects as keys, instead of the values.

how to get key from respective value in a NSDictionary?

how to get key from respective value in a NSDictionary?
I am aware of allKeys function but do we have a method which returns a single key for a single value.
Well because a value can be in a NSDictionary multiple times, there is no way to just say "Give me the key for this value". But you CAN say "Give me all keys containing this value".
NSArray* arrayOfKeys = [yourDictionary allKeysForObject:myObject];
If the value is only once in the dictionary, you can just extract it, using:
YourObject* o = [arrayOfKeys firstObject];
But, always do a NIL and count check on this array. Out of bounds exceptions ahead!
P.S. Credits to #Hagile for firstObject method instead of objectAtIndex:0

What is the best way to get at nested dictionaries from a third party plist?

I have a IOS plist generated by a third party's app I am trying to interface to, consequently I cannot modify the format of the plist. The part that is giving me trouble is an array of Dictionaries, the cardList array. I have loaded the plist into a NSMutableDictionary with no problem and can 'dump' the cardList and colorLabelList arrays.
First Question: What is the best way to access each member of the Item array's? i.e., draft, label, etc. for each of the cards in the list.
2nd Question: Is my 'loading into a NSMutableDictionary' approach the best choice?
Here is the layout of the plist:
cardlist Array
item 0 Dictionary
draft boolean
label string
notes string
...
item 1 Dictionary
draft
label
notes
...
name string
sortOrder number
Use NSMutableDictionary only if you are actually going to change the data, otherwise use a standard NSDictionary (this is more of style thing, the actual implementation does not really change).
If you want to cycle through the cardlist array, do the following:
//This will enumerate through the array element by element
for (NSMutableDictionary *dictionary in cardlist) {
//Ok, now we have a dictionary from cardlist
//Let's print the items to the console
NSLog(#"draft: %i", [dictionary valueForKey:#"draft"]); //Note, there are better ways print print a bool to the log, but this will work for now
NSLog(#"label: %#", [dictionary valueForKey:#"label"]);
NSLog(#"notes: %#", [dictionary valueForKey:#"notes"]);
}
That should go through all of your cardlist array and print the values.

Resources