how to set the parameters in dictionary values - iphone

I am saving the data in external class file but am getting error while saving the Bool value
as a parameter.
Below is the source code
.savefile.h
-(void) saveDecreasedActivity:(NSInteger) bathing
meal:(NSInteger) meal withTitle:(NSString *)title independentItem:(BOOL)timeItem;
{
NSMutableDictionary *lDataObj = [[NSMutableDictionary alloc] init];
[lDataDict setValue:lSeqCounter forKey:#"seqCounter"];
[lDataObj setValue:timeItem forKey:#"independentItem"];
}
and i have save the data in other class
[saver saveDecreasedActivity:[self.bathingControl selectedSegmentIndex]
meal:[self.mealControl selectedSegmentIndex] withTitle:lTitle independentItem:YES];
It was showing
timeItem is incompatible integer to pointer conversion sending "BOOL" (aka singned char) to parameter of type id
Thanks in advance

You can't store raw types (integers, booleans, etc) in an NSDcitionary, which is a collection of key-value pairs (see docs).
In your case, you can use:
[NSNumber numberWithBool: timeItem];
in:
[lDataObj setValue:[NSNumber numberWithBool: timeItem] forKey:#"independentItem"];

You can only store objects in dictionaries, and BOOL is a type, so you have to wrap it like this:
[dictionary setValue:[NSNumber numberWithBool:aBool] forKey:#"yourKey"];
and retrieve it like this:
BOOL aBool = [[dictionary objectForKey:#"yourKey"] boolValue];
Check the NSNumber class reference for more info.

Related

How can I pass a "MutableArray with full of Objects" to another class by using NSUserDefaults?

How can I pass a "MutableArray with full of Objects" to another class by using NSUserDefaults? I know how to pass "MutableArray"s but this does not work!
So;
I have a MutableArray; 'myCityObjects', and I populate it with objects; 'cities'
In each 'cities' object there are properties like cityName, cityLocation etc...
[myCityObjects addObject:cities];
Now, what I want to do is to pass this MutableArray (filled with objects) to another class by using 'NSUserDefaults';
[[NSUserDefaults standardUserDefaults] setObject: myCityObjects forKey:#"MCO"];
And in the other class,
NSMutableArray *getMyCityObjects = [[NSArray alloc] init];
getMyCityObjects = [[NSUserDefaults standardUserDefaults] mutableArrayValueForKey:#"MCO"];
But it doesn't work! I cannot get myCityObjects in the other class, "getMyCityObjects" is empty. How can I fix that?
Thanks,
E.
NSUserDefaults always returns immutable objects, even if the original object was mutable.
In your first View, You can save value in NSUserDefaults like this:
NSMutableArray *arr= [NSMutableArray arrayWithObjects:#"asd",#"dsa",nil];
[[NSUserDefaults standardUserDefaults] setObject:arr forKey:#"MCO"];
After this in another view, you can retrieve value from NSUserDefaults in this way.
NSMutableArray *abc = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"MCO"]];
Your array is nil because the objects in it (your custom objects) can't be serialised.
Please take a look at the NSCoding protocol. Objects you want to serialise (eg for writing to NSUserDefaults) must implement the methods -encodeWithCoder: and -initWithCoder.
I'm sure you'll find how this is rather easily done searching for the terms I gave you...
I have run into this problem before. The problem with the NSUserDefaults is that it can only contain strings, numbers, and booleans, and arrays or dictionaries of those types of values. My solution is to get around that by storing all the properties in NSDictionaries.
Create two class functions on your "cities" class (I'm calling it CityClass):
+(NSDictionary *)dictionaryFromCity:(CityClass *)myCity {
NSDictionary *returnDict = #{#"keyForIntProperty" : myCity.intProperty, #"keyForFloatProperty" : myCity.floatProperty, #"keyForNSStringProperty", myCity.NSStringProperty"};
return returnDict;
}
+(CityClass *)cityFromDictionary:(NSDictionary *)myDict {
CityClass *returnCity = [[CityClass alloc] init];
returnCity.intProperty = [[myDict objectForKey:#"keyForIntProperty"] intValue];
returnCity.floatProperty = [[myDict objectForKey:#"keyForFloatProperty"] floatValue];
returnCity.NSStringProperty = [myDict objectForKey:#"keyForNSStringProperty"];
//any other setup for the CityClass
return returnCity;
}
Now you can store and retrieve your objects without a problem using the new functions:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
//store a CityClass object
NSDictionary *storageDict = [CityClass dictionaryFromCity:cityToStore];
[defaults setObject:storageDict forKey:#"keyForCity"];
//retrieve a CityClass object
NSDictionary *retrieveDict = [defaults objectForKey:#"keyForCity"];
CityClass *retrievedCity = [CityClass cityFromDictionary:retrieveDict];
What you can do here is create a Constructor in your other class for e.g.
-(void)initWithArrayOfObject:(NSMutableArray *)arr_OfObjects;
{
arr_SecondClassArrayOfObjects = [[NSMutableArray alloc]initWithArray:arr_OfObjects];
}
From your first class send this array as :
[objOfSecondClass initWithArrayOfObject: myCityObjects];

How to retrieve String from NSDictionary in objective C?

I am trying to retrieve the value for a key in a NSDictionary. The dictionary has been initialised with key value pairs both of type string. The trouble is, I cannot seem to retrieve the value with I call objectForKey or valueForKey.
I am able to iterate over the dictionary and print both keys and values.
Can someone point out where im going wrong? Here is my code...
//Set up dictionary with options
keys = [NSArray arrayWithObjects:#"red", #"blue", nil];
values = [NSArray arrayWithObjects:#"1.7", #"2.8", nil];
conversionOptions = [NSDictionary dictionaryWithObject:values
forKey:keys];
Then this is called on the select row in a picker
NSLog(#"... %#", [keys objectAtIndex:row]); //prints out the key
NSString *theString = [keys objectAtIndex:row]; //save it as a string
NSLog(#"The string is... %#", theString); //print it out to make sure im not going crazy
NSLog(#"the value is : %#",[conversionOptions objectForKey:theString]); // I just get NULL here
//NSLog(#"the value is : %#",[conversionOptions valueForKey:theString]); // This doesn't work either, I just get NULL
You're creating a dictionary with an array as the only key and an array for its value! You want the dictionaryWithObjects:forKeys: (plural) factory, not dictionaryWithObject:forKey: (singular) so that each element of the keys array will be used as a distinct key for the respective element of the values array.
I find the dictionaryWithObjectsAndKeys: factory to be more useful most of the time, e.g.:
conversionOptions = [NSDictionary dictionaryWithObjectsAndKeys:#"1.7", #"red", #"2.8", #"blue", nil];
This is how you retrieve a string from a dictionary object
NSString * string = [dictionary objectForKey:#"stringKey"];
Use objectForKey: not valueForKey:.
Make sure conversionOptions is non-nil when you call objectForKey: (which is the right method).
And, yeah, derp -- I missed that the wrong factory method was used. You could do dictionaryWithObjects:andKeys: or do what pmjordan said said.
You absolutely must use objectForKey:, though. valueForKey: is specific to KVC.

How can I use an integer value as 'key' to set value in NSMutableDictionary?

How can I use an integer value as 'key' to set a float value in NSMutableDictionary ?
As NSDictionarys are only designed to deal with objects, a simple way to do this is to wrap the integer and float in a NSNumber object. For example:
NSMutableDictionary *testDictionary = [[NSMutableDictionary alloc] init];
[testDictionary setObject:[NSNumber numberWithFloat:1.23f]
forKey:[NSNumber numberWithInt:1]];
NSLog(#"Test dictionary: %#", testDictionary);
[testDictionary release];
To extract the relevant value, simply use the appropriate intValue, floatValue, etc. method from the NSNumber class.
You can use NSMapTable as it supports integer keys and/or values directly. No need to box/unbox through NSNumber, but it is also slightly more difficult to set up and use.
It needs to be an object, so use [NSNumber numberWithInt:myInteger] instead.
Then, retrieve it with -integerValue

NSUserDefaults won't save NSDictionary

I'm writing an application which uses NSUserDefaults as the data storage mechanism, and am hitting a problem when trying to save data (that conforms to the Property List protocols):
+ (BOOL)storeAlbum:(Album *)album
{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *albums = (NSMutableDictionary *)[prefs objectForKey:#"my_adventure_book_albums"];
NSLog(#"Existing albums: %#",albums);
if (!albums)
albums = [NSMutableDictionary dictionaryWithObject:album forKey:#"album"];
else
[albums setObject:album forKey:#"album"];
NSLog(#"%#",album);
[prefs setObject:albums forKey:#"my_adventure_book_albums"];
return [prefs synchronize];
}
I get this output:
2010-06-29 17:17:09.929 MyAdventureBook[39892:207] Existing albums: (null)
2010-06-29 17:17:09.930 MyAdventureBook[39892:207] test
2010-06-29 17:17:09.931 MyAdventureBook[39892:207] *** -[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value '{
album = test;
}' of class 'NSCFDictionary'.
The description method of Album looks like:
- (NSString *)description
{
// Convert to a NSDictionary for serializing
if (!title) title = #"";
if (!date) date = [NSDate dateWithTimeIntervalSinceNow:0];
if (!coverImage) coverImage = #"";
if (!images) images = [[NSArray alloc] initWithObjects:#"",nil];
//NSDictionary *dict = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:title,date,coverImage,images,nil] forKeys:[NSArray arrayWithObjects:#"title",#"date",#"coverImage",#"images",nil]];
//NSDictionary *dict = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:title,nil] forKeys:[NSArray arrayWithObjects:#"title",nil]];
//return [dict description];
return #"test";
}
All of the commented-out lines have the same result, so I just decided to see if the NSString "test" would work, which it (of course) doesn't.
But the object you put inside the dictionary, an Album* is most likely not a property list object, is it? Every object, all the way down, needs to be a property list object for this to work. A description method isn't good enough to make this happen.
As a workaround, you can use NSCoding and an NSKeyedArchiver to write out your dictionary to an NSData, which you can store among the preferences.
You can only put basic foundation types into a property list. NSUserDefaults writes preferences out as a property list. See here for property list allowed types. In a nutshell, it is numbers, strings, data, dates, and arrays and dictionaries of those. Dictionaries must have string keys.
NSUserDefaults always returns immutable objects, so you can't just cast them to mutable. Do [prefs objectForKey:#"my_adventure_book_albums"] mutableCopy] (and remember to release it when finished).

Why should I use KVC rather than the simple dot syntax when accessing object properties?

There's the option to go the long way, if an receiver class conforms to the NSKeyValueProtocol:
[myInstance setValue:[NSNumber numberWithInt:2] forKey:#"integerProperty"];
or the short way:
myInstance.integerProperty = 2;
what's the point of this KVC method? When is this useful?
First, those aren't the same, the second should be:
myInstance.integerProperty = [NSNumber numbwerWithInt:2];
if integerProperty is an NSNumber.
In general you use the second form when you are doing the most things. You use setValue:forKey: and valueForKey: when you want to dynamically choose the property to store things in. For instance, think about how valueForKeyPath: against an NSArray works (for reference, if you call -valueForKey: against an NSArray it will return an array where each object is the result of asking the corresponding object in that NSArray for that value:
- (NSArray *) valueForKey:(id)key {
NSMutableArray *retval = [NSMutableArray array];
for (NSObject *object in self) {
[retval addObject:[object valueForKey:key]];
}
return retval;
}
In the above case we were able to use valueForKey: to implement our function even though we do not know what the key is beforehand, since it is passed in as an argument.