ObjecTips

Swift & Objective-C で iOS とか macOS とか

UIKit の Private な UIGestureRecognizer その3

前回の続き

id object = [[gestureRecognizer valueForKey:@"targets"] firstObject];

で取り出した Private な UIGestureRecognizerTarget クラスから
target と action を取り出す。

target は KVO で取得できる。

id target = [object valueForKey:@"target"];

action の方は KVO を取得しようとすると Exception が起きてしまった。

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIGestureRecognizerTarget 0x7fd852730c90> valueForUndefinedKey:]: this class is not key value coding-compliant for the key action.'

ので、ここではまた Runtime API を使って Ivar 経由で SEL を取得する。
コードは以下

    Ivar ivar = class_getInstanceVariable([object class], "_action");
    SEL action = (__bridge void *)object_getIvar(object, ivar);

object_getIvar の返り値の型 id を SEL にキャストしようとすると

Cast of an Objective-C pointer to 'SEL' is disallowed with ARC

とエラーが起きてしまうので、voidでキャストしている。

target と action が取得できたら後は NSStringFromClassNSStringFromSelector でログ出力に必要な要素が揃う。

ジェスチャーのログとして出力したい numberOfTouchesRequired メソッドUIGestureRecognizer メソッドはジャスチャークラスによって実装されていたりされていなかったりするので、表示するにあたっては respondsToSelector:メソッドが有効かどうかをチェックして有効なら表示するようにする。
また、numberOfTouches numberOfTapsRequired 共に値が0の時はログ表示しない。
これらをまとめると以下のコードになる。

出力結果は以下

UITextTapRecognizer; action=oneFingerTripleTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=1; numberOfTapsRequired=3;

ちょっとログ出力したいだけなのに随分遠回りしてしまった感ある。