Reputation: 8967
So I have the following method:
- (void)readPlist
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"States" ofType:@"plist"];
self.data = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
BOOL value = (BOOL)[self.data valueForKey:@"Arizona"];
NSLog(@"VALUE IS %d", value);
}
It reads the plist fine, it can detect that it has 7 keys, however when I try to print the value out it gives me 32 if it's a no and 24 if it's a yes. What am I doing wrong?
Upvotes: 9
Views: 6787
Reputation: 26652
Thought I would chip in on this. First thing is, how to property define a BOOL value in your plist?
Apple's DTD for plist gives a decent clue:
<!ENTITY % plistObject "(array | data | date | dict | real | integer | string | true | false )" >
and later:
<!-- Numerical primitives -->
<!ELEMENT true EMPTY> <!-- Boolean constant true -->
<!ELEMENT false EMPTY> <!-- Boolean constant false -->
All great, but how does that look in the plist?
Well, for a true value, it would be:
<dict>
<key>employeeId</key>
<integer>1</integer>
<key>name</key>
<string>Joe Smith</string>
<key>worksRemotely</key>
<true/>
</dict>
and of course for false:
<dict>
<key>employeeId</key>
<integer>1</integer>
<key>name</key>
<string>Joe Smith</string>
<key>worksRemotely</key>
<false/>
</dict>
To create an object from the plist, as a keen user of Objectify, I take inspiration from their factory classes. My Employee
class would have these methods:
+ (Employee *)instanceFromDictionary:(NSDictionary *)aDictionary {
Employee *instance = [[Employee alloc] init];
[instance setAttributesFromDictionary:aDictionary];
return instance;
}
that in turn calls:
- (void)setAttributesFromDictionary:(NSDictionary *)aDictionary {
if (![aDictionary isKindOfClass:[NSDictionary class]]) {
return;
}
[self setValuesForKeysWithDictionary:aDictionary];
}
setValuesForKeysWithDictionary:aDictionary
is a member of the NSKeyValueCoding Protocol. That's available with every NSObject
which means as as a subclass of NSObject
, our Employee
class gets that for free.
As long as my Employee class' properties match with the key values specified in the plist, namely employeeId
, name
, and worksRemotely
, then I won't need to do anything else. That method will translate the worksRemotely
boolean specified in the plist to the correct value in my class instance:
@property (assign, nonatomic, getter = isWorkingRemotely) BOOL worksRemotely;
All that's left is to iterate through the plist contents, creating the instances of my desired class, bool included:
NSString *plistPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"employees" ofType:@"plist"];
NSArray *employeeDictionaries = [NSArray arrayWithContentsOfFile:plistPath];
for (NSDictionary *employeeDict in employeeDictionaries) {
Employee *employee = [Employee instanceFromDictionary:employeeDict];
[employees addObject:employee];
}
No doubt I've gone a bit over the top in answering the specific question. However hopefully this can be of use to someone else who stumbled across this question whilst trying to do what I was trying, i.e. create a class with a boolean value in a plist.
Upvotes: 0
Reputation: 3752
valueForKey returns an id. Do this:
NSNumber * n = [self.data valueForKey:@"Arizona"];
BOOL value = [n boolValue];
Upvotes: 24
Reputation: 6813
- (void)readPlist
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"States" ofType:@"plist"];
self.data = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
BOOL value = [[self.data valueForKey:@"Arizona"] intValue];
NSLog(@"VALUE IS %i", value);
}
Upvotes: 1