проблема с чтением NSDictionary из plist со значением BOOL

#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.