web-dev-qa-db-ja.com

Objective Cでクラスメソッドを動的に呼び出す

SomeClassというクラスメソッドを持つObjective CインターフェイスsomeMethodがあるとします。

@interface SomeClass : NSObject {
}

+ (id)someMethod;
@end

他のインターフェイスでは、次のようなクラスで動的にsomeMethodを呼び出すヘルパーメソッドが必要です。

[someOtherObject invokeSelector:@selector(someMethod) forClass:[SomeClass class];

invokeSelectorの実装は何ですか?まったく可能ですか?

- (void)invokeSelector:(SEL)aSelector forClass:(Class)aClass {
   // ???
}
41
GregK

の代わりに:

[someOtherObject invokeSelector:@selector(someMethod) forClass:[SomeClass class];

コール:

[[SomeClass class] performSelector:@selector(someMethod)];

例(GNUstepを使用して...)

ファイルA.h

#import <Foundation/Foundation.h>
@interface A : NSObject {}

- (NSString *)description;
+ (NSString *)action;
@end

ファイルA.m

#import <Foundation/Foundation.h>
#import "A.h"

@implementation A

- (NSString *)description
{
    return [NSString stringWithString: @"A"];
}

+ (NSString *)action
{
    return [NSString stringWithString:@"A::action"];
}

@end

どこか別の場所:

A *a = [[A class] performSelector:@selector(action)];
NSLog(@"%@",a);

出力:

2009-11-22 23:32:41.974 abc[3200] A::action

http://www.cocoabuilder.com/archive/cocoa/197631-how-do-classes-respond-to-performselector.html からの素晴らしい説明:

「Objective-Cでは、クラスオブジェクトはその階層のルートクラスのすべてのインスタンスメソッドを取得します。これは、NSObjectから派生するすべてのクラスオブジェクトが、performSelector:を含むすべてのNSObjectのインスタンスメソッドを取得することを意味します。」

83
stefanB

Objective-Cでは、クラスもオブジェクトです。ただし、ルートオブジェクトのクラスメソッド(CocoaではNSObjectまたはNSProxy)を呼び出すことができるため、クラスオブジェクトの扱いは異なります。

したがって、NSObjectで定義されているすべてのインスタンスメソッドをクラスオブジェクトで使用することも可能であり、クラスメソッドを動的に呼び出す正しい方法は次のとおりです。

[aClass performSelector:@selector(aSelector)];

Apple docs はもう少し具体的です。

4
Adrian

これを自分で実装するべきではありません。

NSObjectプロトコルには performSelector: これを正確に行うメソッド。

2
Ben S

この組み込みメソッドはあなたが望むものですか?

id objc_msgSend(id theReceiver, SEL theSelector, ...)

(この関数については ランタイムリファレンスドキュメント を参照してください。)

2
vanja.