あるメソッドをクラスが持っているかを判定する : Objective-C プログラミング

PROGRAM


あるメソッドをクラスが持っているかを判定する

Objective-C では、あるメソッドがクラスに実装されているかを、実行時に調べられるようになっています。

この機能を利用することで、たとえば @protocol で @optional 指定したデリゲートメソッドが実装されている場合に実行するといった処理や、iOS の新バージョンで実装されたメソッドがある場合にだけ実行するといった処理を、プログラミングできるようになります。

 

例えば、UITableViewDataSource プロトコルを実装しているインスタンス dataSource で、プロトコルに定義されている "-tableView:titleForHeaderInSection:" メソッドが実装されているかを調べたい場合は、次のようにします。

// dataSource に "-tableView:titleForHeaderInSection:" メソッドが実装されているかを調べます。

if ([dataSource respondsToSelector:@selector(tableView:titleForHeaderInSection:)])

{

// 実装されている場合は、例えば実行します。

title = [(id<UITableViewDataSource>)dataSource tableView:tableView titleForHeaderInSection:section];

}

上記の例では、呼び出しのときに dataSource を "id<UITableViewDataSource>" 型でキャストしていますが、インスタンスを格納している変数の型が UITableViewDataSource プロトコルを実装していれば、不要です。

これは単に、ビルド時にメソッドが実装されていないことを知らせるエラー "No visible @interface for '****' declares the selector '***'" を回避するために指定しています。

 

派生先から、親クラスがメソッドを実装しているかを調べる

通常は "-respondsToSelector:" メソッドを使用することで、そのインスタンスがメソッドを実装しているかを適切に知ることができます。

ただし、たとえば UITableViewDataSource プロトコルを実装しているクラスがあったとして、そのクラスから派生させたクラス内から、親クラスがメソッドを実装しているかを知ろうとしたときには、"-respondsToSelector:" メソッドでは正しく判定できない場合があります。

 

たとえば、派生クラスで UITableViewDataSource プロトコルに定義されている "-tableView:titleForHeaderInSection:" メソッドを実装して、そこから親クラスのメソッドを呼び出そうとしたとします。

このとき、このメソッドの実装は任意のため、親クラスでこれを実装しているとは限りません。

 

ここで super に対して "-respondsToSelector:" メソッドを使っても、自分自身に実装されている方を見て YES を返してしまうため、正しい処理を行うことができません。

そんなときには次のようにして、メソッドが実装されているかを判定します。

// 親クラスに "-tableView:titleForHeaderInSection:" メソッドが実装されているかを調べます。

if ([[self superclass] instancesRespondsToSelector:@selector(tableView:titleForHeaderInSection:)])

{

// 実装されている場合は、例えばそれを実行します。

title = [super tableView:tableView titleForHeaderInSection:section];

}

このように、自身の親クラスを取得する superclass と、クラスインスタンスの instancesRespondsToSelector: を組み合わせて使用することで、親クラスのメソッド実装を判定しています。

 

もっとも、親クラスのメソッドが実装されているかは、プログラミングをしている段階で知れることが多いと思うので、わざわざこのようにして実装判定をする機会は稀かもしれません。

それでも @optional なメソッドを持つプロトコルに準拠しているクラスを改修するような場合、派生クラスでそれらの @optional なメソッドをこの方法で実装判定されていれば、改修の負担がずいぶん軽減されると思います。

[ もどる ]