КВО с неизвестным наблюдаемым объектом до выполнения - PullRequest
0 голосов
/ 03 апреля 2011

У меня есть класс «Компас», который предназначен для наблюдения за другим классом «SensorA», «SensorB» или «SensorC». Проблема в том, что я не знаю наблюдаемый класс до выполнения. Я использовал отражения для создания экземпляра во время выполнения. Я не знаю, правильно ли я практикую КВО при этом.


---Another Extern Class---
Compass *aCompass= [[AnalogCompass alloc] initWithCompassName:@"ABC" andID...];

---The oberserving Compass.m Class---
- (id)initWithCompassName:(NSString *)CompassName
                     andIid:(int)Iid

                     showAnalog:(NSString *)ShowAnalog
                     showDigital:(NSString *)ShowDigital

{
    if (self = [super init])
    {

        super.iid = Iid;
        super.CompassName = CompassName;

        showAnalog=ShowAnalog;
        showDigital=ShowDigital;

        Class unknown_cls;

        unknown_cls = [[NSClassFromString(super.CompassName) alloc]init];

        [unknown_cls addObserver:self forKeyPath:showAnalog options:NSKeyValueObservingOptionNew context:NULL];
        [unknown_cls addObserver:self forKeyPath:showDigital options:NSKeyValueObservingOptionNew context:NULL];
}  
 }


- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{

    NSLog(@"IN?");

//             [super observeValueForKeyPath:keyPath
//   
//                         ofObject:object
//   
//                           change:change
//   
//               context:context];

}


---Example of the oberserved SensorA Class---
@interface SensorA : NSObject { 

double xPosition;
...
}

@property (assign) double depthInFeet;

- (id)initWithLineToParse:(NSArray *) fields;

@end

Когда я делаю изменения как self.xposition = позиция; в любом из моих наблюдаемых и отраженных классов датчиков (SensorA, SensorB, SensorC) «наблюдаемый-значение-KeyPath: (NSString *) keyPath ofObject: (id) изменение объекта: (NSDictionary *) изменение контекста: (void *) context» по моему наблюдателю компас не называется. Я предполагаю, что это как-то связано с отражением и, возможно, с соответствующими ограничениями такого рода техники. Или, может быть, потому что отражая с

unknown_cls = [[NSClassFromString(super.CompassName) alloc]init];
а не с
unknown_cls = [[NSClassFromString(super.CompassName) alloc]initWithLineToParse:array];

Как заставить это работать на меня? Может быть, это неправильная попытка наблюдать? Спасибо за помощь.

1 Ответ

2 голосов
/ 03 апреля 2011

Я думаю, что проблема в том, что вы пытаетесь использовать класс в качестве экземпляра.

У вас есть

Class unknown_cls

, и вам действительно нужен экземпляр неизвестного класса для использованияв качестве цели для регистрации КВО.

id compass = [[NSClassFromString(CompassName) alloc] init];

Теперь вы можете использовать переменную 'compass' для регистрации наблюдателей KVO.


Просто чтобы прояснить мое понимание ваших классов и их отношений:

AnalogCompass - это класс, который выступает в качестве наблюдателя одного или нескольких Sensor.Когда создается экземпляр AnalogCompass, он должен регистрироваться как наблюдатель для именованного класса Sensor.

Класс Sensor объявляет одно свойство, которое можно наблюдать: depthInFeet

Если это точное представление ваших двух классов, ваш код никогда не будет работать.Ваш экземпляр AnalogCompass не получает ссылок на экземпляры датчика, которые он должен наблюдать.Вы также пытаетесь наблюдать свойство (xposition), которое никогда не было объявлено наблюдаемым свойством Sensor.

Я предполагаю, что в вашем приложении есть по крайней мере один экземпляр AnalogCompass и один экземпляр Sensor.Предполагается, что экземпляр AnalogCompass наблюдает за изменениями в экземпляре датчика.

Чтобы эта работа работала с использованием KVO, вам нужно минимально сделать что-то вроде этого:

AnalogCompass *someCompass = ...;
Sensor *someSensor = ...;

/* Register someCompass as an observer of the 'xposition' 
property of someSensor */

[someSensor addObserver:someCompass forKeyPath:@"xposition" 
                options:0 context:NULL];

Вам также необходимообъявите, что у класса Sensor есть наблюдаемое свойство с именем 'xposition'.

 @interface Sensor : NSObject
 @property (nonatomic, assign) float xposition;
 @end

 @implementation Sensor
 @synthesize xposition;
 @end

Если вы хотите выполнить настройку KVO в инициализаторе AnalogCompass, как, кажется, ваш код делает выше, вам нужночто-то вроде этого:

@interface AnalogCompass : NSObject
{
    Sensor *sensor;
}
@end


@implementation AnalogCompass

- (id) initWithSensor:(Sensor *)aSensor 
{
    self = [super init];
    if (!self) return nil;

    sensor = [aSensor retain];

    [sensor addObserver:self forKeyPath:@"xposition" 
                options:0 context:NULL];

    return self;
}

- (void) dealloc
{
    [sensor removeObserver:self forKeyPath:@"xposition"];
    [sensor release];
    [super dealloc];
}

- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 
                         change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"xposition"])
    {
      // Do something interesting with the value.
    }

    else
    {
      /* super gets to handle it */
      [super observeValueForKeyPath:keyPath ofObject:object 
                          change:change context:context];
    }
}
@end

Если у вас будет несколько видов классов Sensor, вам нужно объявить общий подкласс (например, Sensor), который имеет свойство, которое вы хотите наблюдать (например xposition).Альтернативно вы можете определить @protocol, который реализуют все классы Sensor, который, в свою очередь, определяет свойство, которое вы хотите наблюдать.

Я думаю, что вы можете избежать использования отражения / самоанализа.Ваше приложение будет иметь коллекцию датчиков и некоторое количество объектов Compass, живых во время выполнения.Что-то в вашем приложении будет отслеживать их (например, какой-то другой объект или делегат приложения поддерживает NSArray или NSSet датчиков и / или компасов.

Возможно, ваш класс Compass собирается создать свой собственныйвнутренний объект Sensor в его инициализаторе? Из вашего кода не совсем понятно, что происходит. Однако в какой-то момент вам понадобится один объект Compass и один объект Sensor для регистрации KVO между ними.

...