2009-05-22 17 views
2

私は1つのUIViewControllerに使用するいくつかのデータソースを持っています。私のビューコントローラは、実行時に特定のプロパティの状態に従うために、KeyValue Observingを使用します。私がdataSourceを交換するとき、私はそれらのプロパティの観察を停止する必要があります。問題は、私は、実行時にデータソースのクラスのわからないんだけど、そのため、このようなものが有効ではありません、次のとおりです。実行時にIDを具体的なクラスに動的に型変換する方法はありますか?

if (aDataSource != dataSource) { 
    // Ensure we stop observing the existing dataSource, otherwise bad stuff can happen. 
    [dataSource removeObserver:self forKeyPath:@"someKeyPath"]; // not valid, compiler doesn't know what class dataSource is. 
    [dataSource release]; 
    dataSource = [aDataSource retain]; 
} 

コンパイラは、オブジェクトのインターフェイスを知るために具象クラスを必要とします。この特定のケースでdataSourceのクラスを取得するにはどうしたらいいですか?上記のremoveObserver:forKeyPath:selectorのdataSourceをtypcastしますか? NSStringインスタンスのクラスの名前をキャッシュして、それを私が切り替えるたびに参照するよりも、ダイナミックでスマートなものが好きです。意味は、私はいつものような何かをすることができる:

NSString *lastDataSource = @"MyClass"; 
Class foo = [NSClassFromString(lastDataSource)]; 

ありがとう。

答えて

6
  1. id foo = ...; 
    [foo removeObserver:self forKeyPath:@"someKeyPath"]; 
    

    コンパイラは、タイプidを持つオブジェクトとしてそれで罰金になります(限り、署名は、コンパイラに知られている)任意のメッセージを受け付けます。あなたが持っている場合

  2. は今:

    警告: '-removeObserver:forKeyPath:' プロトコル

    では見られない

    id<NSObject> foo = ...; 
    [foo removeObserver:self forKeyPath:@"someKeyPath"]; 
    

    をコンパイラはあなたに警告を与えますこれは、KVOメソッドが定義されているNSObjectクラスではなく、NSObjectプロトコルを参照しているためです。

  3. しかし、あなたが持っている場合:あなたは、クラスNSObjectのを使用している。この場合のように、細かすぎるコンパイルします

    NSObject* foo = ...; 
    [foo removeObserver:self forKeyPath:@"someKeyPath"]; 
    

関連リンク:

2

あなたはそれが無効なのはどういう意味ですか?コンパイルエラーが出ますか?

Objective-Cは、デフォルトでオブジェクトの動的な型指定をサポートしています。コンパイラがそのオブジェクトがそのメソッドをサポートしていることを静的型から保証できない場合でも、Objective-Cの任意のオブジェクトに対して任意のメソッドを呼び出すことができるはずです。

+0

いいえ、タイプIDがになっても、「-removeObserver:forKeyPath:」プロトコルに見つかりません –

+0

newacctのコメントは正しいですし、それを下降させる。プログラマがメソッドが実行時に確保されることが確実である限り、警告は無害です。 ObjCはダックタイピングと呼ばれるコンセプトに基づいています。 – harms

+0

その上にプロトコルを置かないとどうなりますか?ちょうど "id"。何を手に入れますか? – newacct

1

NSObject *にキャストする必要があると思います。その理由は、KVOメソッドが(NSObjectプロトコルにはないためです)。あなたはこのようにコーディングすると

1

ちょうど私がアプローチは、あなたがして概説することを追加してみましょう...

NSString *lastDataSource = @"MyClass"; 
Class foo = [NSClassFromString(lastDataSource)]; 

...もちろんの意志クラス「foo」が唯一の実行時に計算されますから、あなたのコンパイル時の警告をSUPRESSすることはできません。したがって、プログラマが "foo"というクラスが "MyClass"クラスになることをコードから明示的に見ることはできますが、これはコンパイラにとっては明確ではないので、 "MyClass"メソッドが "myMethod:"の場合は"foo"と宣言されたオブジェクトにそのメッセージを送信すると、コンパイラの警告が表示されます。

私はあなたがこれを理解していると思っていますが、そのアプローチがあなたの問題を解決しない理由を明確にする方が良いでしょう。

関連する問題