iOS アプリ開発に関連するトピックを提供しています。

iOS のタッチイベントをシミュレートする FakeTouch

iOS 端末ではユーザーが画面をタッチすると、 UITouch を内包した UIEvent が生成されアプリに渡されます。 UITouch や UIEvent はイニシャライザが公開されていないため通常はアプリからは生成できませんが、プライベート API を使用することでその制限を回避できます。

その技術を応用し、ユーザー操作で発生したタッチイベントを記録、後から再生することで画面の自動操作を行うサンプルアプリを作成しました。

github.com

Example ディレクトリ内にあるプロジェクトを実行するとサンプルアプリが起動します。

f:id:watanabetoshinori:20190212152929p:plain

左のボタンで操作を記録し、右のボタンで直前に記録した一連の操作をシミュレートします。 主要なコードはフレームワークにしてあるので、お持ちのプロジェクトに取り込んで頂ければ同様の処理を実装できます。

UIEvent, UITouch のシミュレート

UITouch をシミュレートするコードは iOS 用のテスティングフレームワークである KIF が提供するコードを流用しています。

github.com

また、KIF のコードを使用した同種のライブラリ PTFakeTouch 、ZSFakeTouch の実装を参考にしています。

github.com

github.com

UIEvent や UITouch のシミュレート自体はこれらの OSS が既に実施しているので、今回のサンプルアプリでは以下の点を実装することを目的としました。

  • Swift で実装する
  • KIF から UITouch のシミュレートに必要な最低限のコードを抜き出す
  • スワイプなどタッチ以外の操作をシミュレートする

シミュレート可能なこと、不可能なこと

サンプルアプリを実装することで、UITouch のシミュレートにより可能なこと、不可能なことが分かりました。

キーボードやアラートのボタン操作はシミュレート可能

Xcode でアプリのView構造をデバッグする*1と分かりますが、キーボードなどはアプリからアクセス可能な UIWindow として View 構造に追加されます。そのため、タッチすべき座標が正確に分かれば任意のキーを押下することが可能です。同様にアラートについてもボタンを押下することが可能です。また、WebView に対してタッチイベントをシミュレートすれば表示しているコンテンツを操作することも可能です。

ピンチアウト/インなどもシミュレート可能

タッチだけではなく、もう少し複雑な操作もシミュレート可能でした。WebView で Google Map を表示してピンチアウト/イン操作を記録します。その後、再生を実行するとシミュレートされたタッチイベントでもピンチアウト/インと認識され、地図が拡大/縮小されます。*2

パーミッションダイアログに対してはシミュレート不可

アプリが表示するアラートに対してはタッチイベントをシミュレートできますが、位置情報や Face ID などのプライバシー情報にアクセスする際に表示されるダイアログはアプリの View 構造には追加されないためシミュレートできませんでした。

f:id:watanabetoshinori:20190212160519p:plain

SKStoreProductViewController などに対してはシミュレート不可

SKStoreProductViewController などで表示した内容にアクセスできるか試しましたが、内部で使用されている _UIRemoteView に対してはタッチのシミュレートが行えませんでした。同様に SFSafariViewController もアクセスできませんでした。

f:id:watanabetoshinori:20190212154647p:plain

他のアプリに対してはシミュレート不可

アプリからキーボードにアクセスできるので、逆にキーボードからホストアプリへアクセスできるか試しましたが、エクステンションからは UIApplication へのアクセスが一部制限*3されているため不可能でした。 また、iPad の Split View などでも他のアプリの UIWindow にアクセスできないため、アプリを超えてのタッチイベントのシミュレートはできません。

ユースケース

タッチイベントをシミュレート可能な範囲はアプリ自身が制御可能な範囲に限定されるため、KIF のようにテスティング以外の目的ではタッチイベントのシミュレートが意味をなすようなユースケースはほとんど存在しないように思われます。 社内向けアプリ*4でタッチイベントのシミュレートが必要なアプリであれば活用できるかもしれません。

*1:参照: Debugging View Hierarchies

*2:ただし、Map View では正常に認識されません。これは現在のシミュレートの実装に問題があり完全に再現できていないものと思われます。

*3:参照: Some APIs Are Unavailable to App Extensions

*4:プライベートAPIを使用しているので、AppStoreに提出するアプリに組み込むことはできません。