2011-04-02 97 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