2011-04-02 105 views
0

我有一个类“Compass”,它是另一个类“SensorA”,“SensorB”或“SensorC”的观察者。问题是我不知道运行前观察到的类。我使用反射为了在运行时创建一个实例。 我不知道在做这件事时我是否正确地练习KVO。运行前有未知观察对象的KVO

 

---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 = position; (SensorA,SensorB,SensorC),“observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context” in( )我的观察员指南针没有被调用。我猜测它与反射有关,也许与这种技术的相关限制有关。或者也许是因为反映

unknown_cls = [[NSClassFromString(super.CompassName) alloc]init];
而不是
unknown_cls = [[NSClassFromString(super.CompassName) alloc]initWithLineToParse:array];

如何让我的工作? 这样的观察可能是错误的尝试吗?感谢帮助。

+0

看起来像问题真的是反射,因为我不能调用任何函数,我该怎么做才能动态获取我的实例? – 2011-04-02 22:27:37

+0

我只能从反射的Class实例中调用静态方法吗? – 2011-04-02 22:38:15

+0

您将看到showAnalog的内存问题, showDigit一个实例变量。您正在使用简单分配来捕获参数值,但这不够好。您需要保留或复制参数值以正确管理实例变量内存。像showAnalog = [ShowAnalog copy]; – 2011-04-03 03:49:16

回答

2

我认为这里的问题是,你正试图使用​​一个类作为一个实例。

你有

Class unknown_cls 

,你真的需要未知的类的实例作为目标KVO注册使用。

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

现在您可以使用'compass'变量来注册KVO观察者。


只是为了澄清我的类和它们之间的关系的理解:

AnalogCompass是作为一个或多个Sensor的观察者类。当创建AnalogCompass的实例时,它应该将自己注册为名为Sensor类的观察者。

Sensor类声明可以观察到的一个属性:depthInFeet

如果这是你的两个班的准确表示,您的代码将不会起作用。您的AnalogCompass实例没有获取它应该观察的Sensor实例的引用。您还试图观察从未被声明为Sensor的可观察属性的属性(xposition)。

我假定您的应用程序中至少有一个AnalogCompass实例和一个Sensor实例。 AnalogCompass实例应该观察Sensor实例上的更改。

要使用国际志愿者组织这项工作,你需要最低限度地做这样的事情:

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

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

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

您还必须声明的是,传感器类有一个名为“的xPosition”可观察到的财产。

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

@implementation Sensor 
@synthesize xposition; 
@end 

如果你想要做的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),它有你想要观察的属性(例如xposition)。您可能还可以定义所有Sensor类实现的@protocol,然后定义您想要观察的属性。

我认为你可以避免使用反思/内省。您的应用程序将在运行时拥有一组传感器和一些Compass对象。你的应用程序中的某些东西将会跟踪它们(例如,某些其他对象或应用程序代理正在维护NSArray或NSSet传感器和/或罗盘)。

也许你的Compass类将创建它自己的内部传感器对象在它的初始化程序中?从代码中不完全清楚发生了什么事情,但在某些时候,您将需要一个Compass对象和一个Sensor对象,以便在它们之间注册KVO。

+0

感谢您的回答,但它似乎没有区别,如果我使用ID。 – 2011-04-03 08:05:38

+0

非常感谢你的非常详细的评论条例草案。我尝试了另一种方式,同时没有反射,但没有处理它。你的分析以很多方式帮助我。我会在稍后写更多。 – 2011-04-04 07:16:27