多くのアプリには、一定時間が経過すると自動的にログアウトする機能が備わっています。ただし、これらのアプリの中には、API の非アクティビティに基づいてユーザーをログアウトさせるものや、UIView コントロールをオーバーライドしてログアウト タイマーを実装するものもあります。この記事では、hitTest メソッドを使用してこの動作を実現するより良い方法を検討します。また、一部のアプリは、最後のログイン/API 呼び出しと現在時刻との時間差に基づいてログアウトします。最後のアプローチの問題は、デバイス上の時間をログイン時点に手動で設定することで、セッションを常に有効にできることです。
最初のアプローチの問題は、一部のユーザーがコンテンツをスクロールしているだけでバックエンドにリクエストを行っていない場合でもログアウトされる可能性があることです。ユーザーが特定の銀行商品を開く前にその利用規約を読み、ログアウトされると想像してください。これは絶対に避けたいです。
2 番目のアプローチの問題は、特にアプリにカスタム ビューを備えた大規模なコードベースがある場合、既存のコードベースに非アクティブ ログアウト機能を実装するのが難しい場合があることです。
ここで、 hitTest メソッドが非常に役立ちます。
リストされている問題を解決するには、hitTest メソッドを使用したハックを使用できます。
ユーザーのアクティビティ時間を追跡するクラスの実装バージョンがすでにあると仮定しましょう。
これを次の API で表現します。
protocol IUserActivity { func resetInactiveTime() }
extension UIWindow { open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { userActivity.resetInactiveTime() return super.hitTest(point, with: event) } }
以上です!このメソッドは、タップ、スクロール、その他のジェスチャ アクティビティなど、ユーザーが画面上で行うすべてのインタラクティブ イベントでトリガーされるようになります。
UIWindow のサブクラスを宣言し、そこで hitTest メソッドをオーバーライドすることもできます。
iOSのタッチ イベントは通常、デバイスのタッチ スクリーンとのユーザー操作から発生します。
ユーザーが画面にタッチすると、ハードウェアがタッチを検出し、タッチの位置、圧力、持続時間などの情報を含む生のタッチ データのストリームを生成します。
この生のタッチ データはオペレーティング システムによって処理され、UIKit で処理できる高レベルのタッチ イベントに変換されます。オペレーティング システムは、タッチ位置とビュー階層に基づいてタッチ イベントがどの UIWindow オブジェクトに対応するかを判断し、処理のためにそのオブジェクトの UIResponder オブジェクトにタッチ イベントを送信します。
タッチ イベントが発生すると、iOS オペレーティング システムはヒット テスト アルゴリズムを使用して、タッチ イベントがどの UIView オブジェクトまたは UIWindow オブジェクトに対応するかを判断します。
ヒット テスト アルゴリズムは、最上位の UIWindow オブジェクトから開始され、タッチ ポイントを含む最も深いビューが見つかるまで、ビュー階層内の各サブビューを再帰的にチェックします。これは、タッチ ポイントが各サブビューのフレーム内にあるかどうかを確認することによって行われます。
ヒット テストでは、深さ優先の逆プリオーダー トラバーサル アルゴリズムが使用されます。言い換えれば、アルゴリズムは最初にルート ノードにアクセスし、次にそのサブツリーを上位のインデックスから下位のインデックスに移動します。
この種のトラバーサルにより、トラバーサルの反復回数を減らし、タッチポイントを含む最初の最も深い子孫ビューが見つかったら検索プロセスを停止できます。
サブビューは常にそのスーパービューの前にレンダリングされ、兄弟ビューは常にサブビュー配列のインデックスが小さい兄弟ビューの前にレンダリングされるため、これが可能になります。複数の重なり合うビューに特定の点が含まれている場合、右端のサブツリーの最も深いビューが最前面のビューになります(1) 。
ご覧のとおり、トラバース アルゴリズムは、ユーザーがどのビューやコントロールと対話するかに関係なく、常に UIWindow オブジェクトから開始します。
そして、UIWindow クラスの hitTest メソッドでこれらのイベントをインターセプトするだけで、これを目的に使用できることは間違いありません。
それでおしまい!以下のコメント欄でご意見をお聞かせください。