11
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Objective-C] メッセージの転送

Posted at

Objective-Cは非常に動的な言語です。
ランタイムを使って動的にメソッドを追加したり、といったこともできます。
そのために、コンパイル時に存在しないメソッドに対してもメッセージを送る方法が存在します。
(ただし、しっかり対処しないとエラーで落ちます)

これらの機能を実現しているのが転送のメカニズムです。
どういう手順で行われるか、後々役に立ちそうなのでメモとして残しておきます。

まず、大雑把に書くと以下の順にメソッドが呼び出されます。

  1. + (BOOL)resolveInstanceMethod:(SEL)sel
  2. - (id)forwardingTargetForSelector:(SEL)aSelector
  3. - (void)forwardInvocation:(NSInvocation *)invocation

上から順に書いていきます。

resolveInstanceMethod: (resolveClassMethod:)

これはクラスメソッドになっていて、オブジェクトが理解できないメッセージがオブジェクトに対して渡されたときに呼び出されます。
(これはインスタンスメソッドの場合。名前から自明ですね。クラスメソッドの場合は類似のresolveClassMethod:が呼ばれます)

返り値の型を見ると分かる通り、これは対応可能かどうかをBOOLで返します。
そのため、このメソッド内で動的にメソッドを実装するなどする場合に使います。
(動的に追加したあとに、応答可能なことを示すためにYESを返す、というわけです)

実際の例

// setter
void setter(id self, SEL _cmd, id value) {
	//
}
// getter
NSString * getter(id self, SEL _cmd) {
	return @"hoge";
}
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
	NSString *selectorString = NSStringFromSelector(sel);

	if ([selectorString hasPrefix:@"set"]) {
		class_addMethod(self, sel, (IMP)setter, "v@:@");
	}
	else {
		class_addMethod(self, sel, (IMP)getter, "@@:");
	}
}

ちなみにclass_addMethodの最後の引数に変な文字列が渡されていますが、これは返り値と引数の状態を表した文字列です。意味は以下の通りです。

Type 意味
c char
i int
s short
l long
q long long
C unsigned char
I unsinged int
S unsigned short
L unsigned lpng
Q unsigned long long
f float
d double
B C++のbool、またはC99の_Bool
v void
* 文字列 (char *)
@ オブジェクト(idとして定義されているもの)
# クラスオブジェクト(Class)
: メソッドセレクタ(SEL)
[配列型] 配列
{名前=型} 構造体
(型...) 共用体
bnum numビットのフィールド
^型 型へのポインタ
? 不明な型
r const
n in
N inout
o out
O bycopy
R byref
V oneway
11
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?