среда, 29 апреля 2009 г.

Работа со свойствами (property) c помощью KVM

Как вам наверняка известно, Objective-C позволяет быстро создавать сеттеры и геттеры с помощью директив @property и @synthesize

Однако главное на мой взгляд достоинство этих @property в возможностях, представляемых механизмом Key-Value-Mechanisms Об этих возможностях чуть поподробнее:

Имеем класс

@interface ClassWithProperties
...
@property int integerProperty;
@property id idProperty;
@property NSString *strProperty;

 

1. Доступ к свойствам по их имени во время выполнения программы. Имя свойства может быть неизвестно на этапе компиляции и вычисляться только после старта. Обратите внимание, что метод работает только с наследниками NSObject И поэтому примитивные типы должны быть преобразованы в NSValue и NSNumber Обратное преобразование механизм property делает сам автоматически

ClassWithProperties *cl;
 [cl setValue: [NSNumber numberWithInt: 10] forKey: @"integerProperty"];
 [cl setValue: self forKey: @"idProperty"];
 [cl setValue: @"just a string" forKey: @"strProperty"];
 ......
 int i = [[cl valueForKey: @"integerProperty"] intValue];
 NSString *s = [cl valueForKey: @"strProperty"];

2. Иногда  возникает необходимость формировать свойства на этапе выполнения. Чтоб пользователь мог обратиться к 

[cl setValue: @"someValue" forKey: @"AnyNameAsYouWant"]; и  [cl valueForKey: @"AnyNameAsYouWant"];

даже если на этапе компиляции это имя "AnyNameAsYouWant" неизвестно.  Тут на помощь приходят методы NSObject(void)setValue:(id)value forUndefinedKey:(NSString *)key и  (id)valueForUndefinedKey:(NSString *)key переопределив эти методы мы получим возможность сохранять и полученные значения например в NSMutableDictionary.

3. Получение имен всех свойств. Если мы хотим получить значения всех  property класса (например чтобы их сохранить при выходе), то нам нужно сперва получить все имена, а потом через valueForKey можно будет вытащить и значения. Имена всех свойств класса получаются так:

 #import "objc/runtime.h" ........................
 unsigned int outCount;
 objc_property_t *properties = class_copyPropertyList([AnyClassThatYouWant class], &outCount);
 for(int i = 0; i < outCount; i++)
 {
     objc_property_t property = properties[i];
     const char *propName = property_getName(property);
     if(propName)
     {
        NSString *name = [NSString stringWithUTF8String:propName];
       NSLog(name);  
     }
 }
free(properties);



Внимание! подобным образом нельзя получить свойства, которые были объявлены в суперклассе. Если Вам нужны действительно ВСЕ свойства, то есть [NSobject superclass];

Комментариев нет:

Отправить комментарий