読者です 読者をやめる 読者になる 読者になる

ObjecTips

基本Objective-Cで iOS とか OS X とか

UIKit の Private な UIGestureRecognizer その4

Objective-C Tips Private API UIGestureRecognizer

koze.hatenablog.jp

前回の記事で実装した LogGesture() 関数を用いてシステムが自動的に

- (void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer

で設定するジェスチャの中身を調べてみる。

最初に書いたコードが以下で、

koze.hatenablog.jp

UITextField のサブクラスを作って、サブクラスの addGestureRecognizer: メソッドをオーバーライドしてログを出力する想定になっている。
でもこれだと調べたいクラス毎にサブクラスを作らないといけないので、いちいちサブクラスを作らなくて良いように Runtime APImethod_exchangeImplementations を使って UIViewaddGestureRecognizer: メソッドをフックしてログ出力をしてみる。

また前回の関数は

void *LogGesture(UIGestureRecognizer *gestureRecognizer);

で引数にジェスチャを取って関数内で NSLog を呼んでいる。これを今回のログ用に内部で NSLog を呼ばずに NSString * を返すよう変更している。

無理やり1ファイルにしたのでごっちゃりしてしまったけどコピペで試せるコードは以下のような感じ。

Storyboard上のViewに UITextField を置いてこのコードを走らせると以下のようにログ出力される。

{
    UITextField =     (
        "UITextTapRecognizer; action=oneFingerTripleTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=1; numberOfTapsRequired=3;",
        "UITextTapRecognizer; action=oneFingerDoubleTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=1; numberOfTapsRequired=2;",
        "UITextTapRecognizer; action=twoFingerSingleTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=2; numberOfTapsRequired=1;",
        "UITapAndAHalfRecognizer; action=tapAndAHalf:; target=UITextInteractionAssistant;",
        "UILongPressGestureRecognizer; action=twoFingerRangedSelectGesture:; target=UITextInteractionAssistant; numberOfTouchesRequired=2;",
        "UITextTapRecognizer; action=oneFingerTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=1; numberOfTapsRequired=1;",
        "UIVariableDelayLoupeGesture; action=loupeGesture:; target=UITextInteractionAssistant; numberOfTouchesRequired=1;"
    );
    UIWindow =     (
        "_UISystemGestureGateGestureRecognizer; action=(null); target=(null);"
    );
}

おお、_UISystemGestureGateGestureRecognizer とかいう謎な奴が新たに発見された。

Storyboard上で置けそうなViewクラスを片っ端らから置いたログ結果は以下。
Private なクラスが山の様に出てきた。

{
    UICollectionView =     (
        "UIScrollViewDelayedTouchesBeganGestureRecognizer; action=delayed:; target=UICollectionView;",
        "UIScrollViewPanGestureRecognizer; action=handlePan:; target=UICollectionView;"
    );
    UINavigationBar =     (
        "UISwipeGestureRecognizer; action=_handlePopSwipe:; target=UINavigationBar; numberOfTouchesRequired=1;"
    );
    UIPickerColumnView =     (
        "UIScrollViewPanGestureRecognizer; action=handlePan:; target=UIPickerTableView;"
    );
    UIPickerTableView =     (
        "UIScrollViewDelayedTouchesBeganGestureRecognizer; action=delayed:; target=UIPickerTableView;",
        "UIScrollViewPanGestureRecognizer; action=handlePan:; target=UIPickerTableView;"
    );
    UIPickerTableViewWrapperCell =     (
        "UITapGestureRecognizer; action=_tapAction:; target=UIPickerTableViewWrapperCell; numberOfTouchesRequired=1; numberOfTapsRequired=1;"
    );
    UIScrollView =     (
        "UIScrollViewDelayedTouchesBeganGestureRecognizer; action=delayed:; target=UIScrollView;",
        "UIScrollViewPanGestureRecognizer; action=handlePan:; target=UIScrollView;"
    );
    UISearchBar =     (
        "UITapGestureRecognizer; action=tappedSearchBar:; target=UISearchBar; numberOfTouchesRequired=1; numberOfTapsRequired=1;"
    );
    UISearchBarTextField =     (
        "UITextTapRecognizer; action=oneFingerTripleTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=1; numberOfTapsRequired=3;",
        "UITextTapRecognizer; action=oneFingerDoubleTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=1; numberOfTapsRequired=2;",
        "UITextTapRecognizer; action=twoFingerSingleTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=2; numberOfTapsRequired=1;",
        "UITapAndAHalfRecognizer; action=tapAndAHalf:; target=UITextInteractionAssistant;",
        "UILongPressGestureRecognizer; action=twoFingerRangedSelectGesture:; target=UITextInteractionAssistant; numberOfTouchesRequired=2;",
        "UITextTapRecognizer; action=oneFingerTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=1; numberOfTapsRequired=1;",
        "UIVariableDelayLoupeGesture; action=loupeGesture:; target=UITextInteractionAssistant; numberOfTouchesRequired=1;"
    );
    UITableView =     (
        "UIScrollViewDelayedTouchesBeganGestureRecognizer; action=delayed:; target=UITableView;",
        "UIScrollViewPanGestureRecognizer; action=handlePan:; target=UITableView;"
    );
    UITableViewCellContentView =     (
        "UILongPressGestureRecognizer; action=_longPressGestureRecognized:; target=UIPickerTableViewWrapperCell; numberOfTouchesRequired=1;"
    );
    UITableViewWrapperView =     (
        "UIScrollViewDelayedTouchesBeganGestureRecognizer; action=delayed:; target=UITableViewWrapperView;",
        "UIScrollViewPanGestureRecognizer; action=handlePan:; target=UITableViewWrapperView;"
    );
    UITextField =     (
        "UITextTapRecognizer; action=oneFingerTripleTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=1; numberOfTapsRequired=3;",
        "UITextTapRecognizer; action=oneFingerDoubleTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=1; numberOfTapsRequired=2;",
        "UITextTapRecognizer; action=twoFingerSingleTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=2; numberOfTapsRequired=1;",
        "UITapAndAHalfRecognizer; action=tapAndAHalf:; target=UITextInteractionAssistant;",
        "UILongPressGestureRecognizer; action=twoFingerRangedSelectGesture:; target=UITextInteractionAssistant; numberOfTouchesRequired=2;",
        "UITextTapRecognizer; action=oneFingerTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=1; numberOfTapsRequired=1;",
        "UIVariableDelayLoupeGesture; action=loupeGesture:; target=UITextInteractionAssistant; numberOfTouchesRequired=1;"
    );
    UITextView =     (
        "UIScrollViewDelayedTouchesBeganGestureRecognizer; action=delayed:; target=UITextView;",
        "UIScrollViewPanGestureRecognizer; action=handlePan:; target=UITextView;",
        "UITextTapRecognizer; action=oneFingerTripleTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=1; numberOfTapsRequired=3;",
        "UITextTapRecognizer; action=oneFingerDoubleTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=1; numberOfTapsRequired=2;",
        "UITextTapRecognizer; action=twoFingerSingleTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=2; numberOfTapsRequired=1;",
        "UITapAndAHalfRecognizer; action=tapAndAHalf:; target=UITextInteractionAssistant;",
        "UILongPressGestureRecognizer; action=twoFingerRangedSelectGesture:; target=UITextInteractionAssistant; numberOfTouchesRequired=2;",
        "UITextTapRecognizer; action=oneFingerTap:; target=UITextInteractionAssistant; numberOfTouchesRequired=1; numberOfTapsRequired=1;",
        "UIVariableDelayLoupeGesture; action=loupeGesture:; target=UITextInteractionAssistant; numberOfTouchesRequired=1;"
    );
    UIView =     (
        "MKVariableDelayTapRecognizer; action=handleDoubleTap:; target=MKMapGestureController; numberOfTouchesRequired=1; numberOfTapsRequired=2;",
        "UITapGestureRecognizer; action=handleTwoFingerTap:; target=MKMapGestureController; numberOfTouchesRequired=2; numberOfTapsRequired=1;",
        "UILongPressGestureRecognizer; action=handleTwoFingerLongPress:; target=MKMapGestureController; numberOfTouchesRequired=2;",
        "UIPinchGestureRecognizer; action=handlePinch:; target=MKMapGestureController;",
        "UIPanGestureRecognizer; action=handlePan:; target=MKMapGestureController;",
        "_MKUserInteractionGestureRecognizer; action=handleTouch:; target=MKMapGestureController;",
        "UIRotationGestureRecognizer; action=handleRotation:; target=MKMapGestureController;",
        "MKTiltGestureRecognizer; action=handleTilt:; target=MKMapGestureController;",
        "UILongPressGestureRecognizer; action=handleLongPress:; target=MKMapView; numberOfTouchesRequired=1;",
        "UITapGestureRecognizer; action=_handleTapToSelect:; target=MKMapView; numberOfTouchesRequired=1; numberOfTapsRequired=1;",
        "UITapGestureRecognizer; action=_handleTapToDeselect:; target=MKMapView; numberOfTouchesRequired=1; numberOfTapsRequired=1;"
    );
    UIWebBrowserView =     (
        "UIWebTouchEventsGestureRecognizer; action=(null); target=(null);",
        "UITapGestureRecognizer; action=_singleTapRecognized:; target=UIWebBrowserView; numberOfTouchesRequired=1; numberOfTapsRequired=1;",
        "UITapGestureRecognizer; action=_doubleTapRecognized:; target=UIWebBrowserView; numberOfTouchesRequired=1; numberOfTapsRequired=2;",
        "UITapGestureRecognizer; action=_twoFingerDoubleTapRecognized:; target=UIWebBrowserView; numberOfTouchesRequired=2; numberOfTapsRequired=2;",
        "_UIWebHighlightLongPressGestureRecognizer; action=_highlightLongPressRecognized:; target=UIWebBrowserView; numberOfTouchesRequired=1;",
        "UILongPressGestureRecognizer; action=_longPressRecognized:; target=UIWebBrowserView; numberOfTouchesRequired=1;",
        "UIPanGestureRecognizer; action=_twoFingerPanRecognized:; target=UIWebBrowserView;"
    );
    UIWindow =     (
        "_UISystemGestureGateGestureRecognizer; action=(null); target=(null);"
    );
    "_UISwitchInternalViewNeueStyle1" =     (
        "UILongPressGestureRecognizer; action=_handleLongPressNL:; target=UISwitch; numberOfTouchesRequired=1;",
        "UIPanGestureRecognizer; action=_handlePanNL:; target=UISwitch;"
    );
    "_UIWebViewScrollView" =     (
        "UIScrollViewDelayedTouchesBeganGestureRecognizer; action=delayed:; target=_UIWebViewScrollView;",
        "UIScrollViewPanGestureRecognizer; action=handlePan:; target=_UIWebViewScrollView;",
        "UIScrollViewPinchGestureRecognizer; action=handlePinch:; target=_UIWebViewScrollView;"
    );
}