1

私は iOS Big Nerd Ranch の本を読んでいましたが、例の 1 つは、オブザーバーを NSNotificaionCenter に追加する方法を示しています。

    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(orientationChanged:)
                                             name:UIDeviceOrientationDidChangeNotification
                                           object:[UIDevice currentDevice]];

現在、orientationChanged では、方向が NSNotification に投稿されたオブジェクトから取得されます。

- (void)orientationChanged:(NSNotification *)note {
    NSLog(@"orientationChanged  %d", [[note object] orientation]);
 }

私の混乱はこの行にあります: [[note object] orientation]

NSNotification のオブジェクトはidを返すため、コンパイル時にオブジェクトの型が UIDevice であることがわかりません。ただし、コンパイラからエラーが発生することなく、返されたオブジェクトから向きにアクセスできます。コンパイラは、オブジェクト タイプが UIDevice であり、方向へのアクセスが許容されることをどのように認識しますか?

4

2 に答える 2

4

コンパイラはオブジェクト タイプが であることをどのように認識しますUIDeviceか?

そうではありません。

であることがわかりidます。型idは汎用オブジェクト型です。したがって、コンパイラは、メッセージを送信してもエラーなしで受け入れます。存在しないものを送っても。

これは、Objective-C が動的言語であるためです。メソッド呼び出し (メッセージ送信)、バインディング、さらには型も、Objective-C ランタイム ライブラリによって実行時に推測されます。実装されていないメッセージ (「応答」) をオブジェクトに送信すると、コンパイラ エラーの代わりに実行時例外がスローされます。

ちなみに、 へのメッセージidid(したがって、ほとんどの整数など、ポインタ サイズの値が安全に返される可能性があります) を返すか、コンパイラはすべてのクラスで使用可能なすべてのセレクタ名を調べて、型を に一致させようとします。実際に見つかった場合に備えて、見つかったセレクターの 1 つ。

于 2013-03-20T15:58:21.633 に答える
2

Objective-C のメッセージは、コンパイル時ではなく、実行時にメソッドの実装に動的にバインドされます。メソッドを実装していないオブジェクトにメッセージを送信しようとすると、インスタンス例外に送信された認識されないセレクターがスローされます。

「respondsToSelector:」というメッセージをオブジェクトに送信して、オブジェクトがセレクターに応答するかどうかを尋ねることで、この例外がスローされるのを防ぐことができます。このメソッドが YES を返す場合、メッセージを安全に送信できます。これは、プロトコルの一部のメソッドがオプションである可能性があるため、クラスにデリゲートを実装する場合に一般的です。

Objective-C メッセージングの仕組みの詳細については、Apple Objective-C ランタイム プログラミング ガイド ( https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtHowMessagingWorks.html)を参照してください。 #//apple_ref/doc/uid/TP40008048-CH104-SW1

于 2013-03-20T16:03:37.020 に答える