Как безопасно выводить пользователей из приложений iOS с тайм-аутом бездействия

Как безопасно выводить пользователей из приложений iOS с тайм-аутом бездействия

15 мая 2023 г.

Во многих приложениях есть функция автоматического выхода из системы после определенного периода бездействия. Однако некоторые из этих приложений выходят из системы на основе бездействия API, в то время как другие реализуют таймер выхода, переопределяя элементы управления UIView. В этой статье мы рассмотрим лучший способ добиться такого поведения с помощью метода hitTest. А некоторые приложения выводят вас из системы из-за разницы во времени между последним входом в систему/вызовом API и текущим временем. Проблема с последним подходом заключается в том, что вы можете поддерживать постоянную активность сеанса, вручную устанавливая время на устройстве в момент входа в систему.

Проблема с первым подходом заключается в том, что некоторые пользователи могут выйти из системы, даже если они только прокручивают контент и не делают никаких запросов к серверной части. Представьте себе пользователя, который читает условия определенного банковского продукта перед открытием и выходит из системы. Мы определенно хотим избежать этого.

Проблема со вторым подходом заключается в том, что может быть сложно реализовать функцию выхода из системы по бездействию в существующей кодовой базе, особенно если приложение имеет большую кодовую базу с настраиваемыми представлениями.

Именно здесь метод hitTest может быть очень полезен.

Короткий ответ

Мы можем использовать хак с методом hitTest, чтобы решить перечисленные проблемы.

Предположим, что у нас уже есть реализованная версия класса, отвечающего за отслеживание времени активности пользователя.

Мы собираемся выразить это с помощью следующего API:

protocol IUserActivity {
    func resetInactiveTime()
}

Теперь давайте объявим расширение UIWindow в нашем приложении:

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 верхнего уровня и рекурсивно проверяет каждое подпредставление в иерархии представлений, пока не найдет самое глубокое представление, содержащее точку касания. Он делает это, проверяя, находится ли точка касания внутри фрейма каждого подвида.

Тестирование на попадание использует алгоритм обратного предварительного порядка обхода в глубину. Другими словами, алгоритм сначала посещает корневой узел, а затем обходит его поддеревья от более высоких индексов к более низким.

Hit test traversing algorithm

Этот вид обхода позволяет сократить количество итераций обхода и остановить процесс поиска, как только будет найдено первое самое глубокое представление-потомок, содержащее точку касания.

Это возможно, поскольку подпредставление всегда отображается перед своим суперпредставлением, а родственное представление всегда отображается перед родственными представлениями с более низким индексом в массиве подпредставлений. Когда несколько перекрывающихся представлений содержат определенную точку, самое глубокое представление в крайнем правом поддереве будет самым передним представлением(1) .

Как мы видим, алгоритм обхода всегда начинается с объекта UIWindow, независимо от того, с каким представлением или элементом управления взаимодействует пользователь.

И мы определенно можем использовать это для нашей цели, просто перехватывая эти события в методе hitTest класса UIWindow!

Вот оно! Дайте мне знать, что вы думаете в комментариях ниже.


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE