#iphone #objective-c #ipad #nsdictionary
#iPhone #objective-c #iPad #nsdictionary
Вопрос:
Итак, у меня есть следующий метод:
- (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);
}
Он отлично считывает список, может определить, что у него 7 ключей, однако, когда я пытаюсь распечатать значение, оно выдает мне 32, если это нет, и 24, если это да. Что я делаю не так?
Ответ №1:
valueForKey возвращает идентификатор. Сделайте это:
NSNumber * n = [self.data valueForKey:@"Arizona"];
BOOL value = [n boolValue];
Комментарии:
1. Вы не должны использовать
valueForKey:
. ИспользуйтеobjectForKey:
или в наши дни используйте современный синтаксисNSNumber * n = self.data[@"Arizona"];
Ответ №2:
- (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);
}
Ответ №3:
Думал, что я бы подключился к этому. Во-первых, как определить свойство BOOL value в вашем plist?
DTD от Apple для plist дает неплохую подсказку:
<!ENTITY % plistObject "(array | data | date | dict | real | integer | string | true | false )" >
и позже:
<!-- Numerical primitives -->
<!ELEMENT true EMPTY> <!-- Boolean constant true -->
<!ELEMENT false EMPTY> <!-- Boolean constant false -->
Все замечательно, но как это выглядит в plist?
Ну, для истинного значения это было бы:
<dict>
<key>employeeId</key>
<integer>1</integer>
<key>name</key>
<string>Joe Smith</string>
<key>worksRemotely</key>
<true/>
</dict>
и, конечно, для false:
<dict>
<key>employeeId</key>
<integer>1</integer>
<key>name</key>
<string>Joe Smith</string>
<key>worksRemotely</key>
<false/>
</dict>
Чтобы создать объект из plist, я, как заядлый пользователь Objectify, черпаю вдохновение в их заводских классах. У моего Employee
класса были бы эти методы:
(Employee *)instanceFromDictionary:(NSDictionary *)aDictionary {
Employee *instance = [[Employee alloc] init];
[instance setAttributesFromDictionary:aDictionary];
return instance;
}
это, в свою очередь, вызывает:
- (void)setAttributesFromDictionary:(NSDictionary *)aDictionary {
if (![aDictionary isKindOfClass:[NSDictionary class]]) {
return;
}
[self setValuesForKeysWithDictionary:aDictionary];
}
setValuesForKeysWithDictionary:aDictionary
является членом протокола NSKeyValueCoding. Это доступно с every NSObject
, что означает, что как подкласс NSObject
, наш Employee
класс получает это бесплатно.
До тех пор, пока свойства моего класса Employee совпадают со значениями ключей, указанными в plist, а именно employeeId
, name
, и worksRemotely
, тогда мне больше ничего не нужно будет делать. Этот метод преобразует worksRemotely
логическое значение, указанное в plist, в правильное значение в экземпляре моего класса:
@property (assign, nonatomic, getter = isWorkingRemotely) BOOL worksRemotely;
Все, что осталось, это перебирать содержимое plist, создавая экземпляры нужного мне класса, включая bool:
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];
}
Без сомнения, я немного перегнул палку, отвечая на конкретный вопрос. Однако, надеюсь, это может быть полезно кому-то еще, кто наткнулся на этот вопрос, пытаясь сделать то, что я пытался, т. Е. Создать класс с логическим значением в plist.