-(IMP)methodForSelectorと+(IMP)instanceMethodForSelectorの違い

2097 ワード

ガイド人


今日エンコーディング中に、何気なく-(IMP)methodForSelector関数を見て、普段よく使う+(IMP)instanceMethodForSelector関数を連想しました.この2つの関数は文字通り意味が近いが,同時に存在する以上,両者には違いがあるに違いない.そこで,開発ドキュメントとコードテストを組み合わせて,いくつかの探索を行った.
+ (IMP)instanceMethodForSelector:(SEL)aSelector
機能概要:指定したsSelectorに従って、クラスのインスタンスメソッドのリストを巡回し、対応する関数ポインタを返します.2つの点に注意する必要があります.1、これはクラス関数で、呼び出し者はClassです.二、関数が結果を返すタイプは、クラス関数ポインタではなくインスタンス関数ポインタです.
コードテスト:
@interface TestObject : NSObject
@end

@implementation TestObject

 - (void)testFun
  {
  }

int main(int argc, const char * argv[])
 {
      IMP p = [TestObject instanceMethodForSelector:@selector(testFun)];
      NSLog(@"%p " , p);
      
      return 0;
 }

出力結果:
 2015-12-21 16:17:02.217 TestProject[2916:166056] 0x100000ad0 

推測:この関数の内部実装中にインスタンスオブジェクトが作成され、インスタンスオブジェクトの関数リストを巡り、指定した関数名に対応する関数ポインタが検索されます.
- (IMP)methodForSelector:(SEL)aSelector
機能概要:指定したsSelectorに従って、呼び出し元関数リストの対応する関数ポインタを返します.2つの点に注意してください.1つは、インスタンスオブジェクト関数であり、呼び出し元はインスタンスオブジェクトであってもよいし、クラスオブジェクトであってもよい(Object Cではクラス自体がオブジェクトである)2つ、関数が結果を返すタイプはインスタンス関数ポインタであってもよいし、クラス関数ポインタであってもよい.コードテスト:
int main(int argc, const char * argv[])
 {
      TestObject obj = [TestObject new];
    
      IMP pObj = [obj methodForSelector:@selector(testFun)];
    
      IMP pClass = [TestObject methodForSelector:@selector(testFun)];

      NSLog(@"%p" , pObj);
      NSLog(@"%p" , pClass);
      
      return 0;
 }    

出力結果:
2015-12-21 16:39:12.711 TestProject[3002:179046] 0x100000ad0
2015-12-21 16:39:12.713 TestProject[3002:179046] 0x7fff8878bd40

結論:上記の出力結果から、インスタンスオブジェクト呼び出し-(IMP)methodForSelectorとクラス呼び出し+(IMP)instanceMethodForSelectorの出力結果は一致し、いずれもインスタンスオブジェクトの関数ポインタであることがわかる.クラスオブジェクト呼び出し-(IMP)methodForSelector出力結果は、クラス自体のクラス関数ポインタです.
概要:この2つの関数は、タイプの違いに加えて、-(IMP)methodForSelector関数の使用範囲が広く、インスタンスオブジェクト関数ポインタを取得したり、クラスオブジェクト関数ポインタを取得したりすることができます.さらに、+(IMP)instanceMethodForSelectorは、インスタンスオブジェクトの関数ポインタをより容易に取得するために、対-(IMP)methodForSelectorのカプセル化に似ています.