如何使用 UINavigationController 中的所有视图和导航控制器的导航控件检测用户活动?
Posted
技术标签:
【中文标题】如何使用 UINavigationController 中的所有视图和导航控制器的导航控件检测用户活动?【英文标题】:How can I detect user activity with all the views in UINavigationController and the navigation controller's navigation controls? 【发布时间】:2016-12-06 22:21:18 【问题描述】:我需要能够检测到任何活动(即非空闲),以便我可以重置倒计时。
我尝试使用UIWindow
sendEvent 路线,但这会导致太多副作用。是否有一种简单的方法来检测是否点击了视图、单击了按钮、用户导航到了下一个屏幕等等?我不需要处理事件或任何事情,如果用户仍在使用导航控制器,我只需要重置计时器。顺便说一句,这个特别的导航控制器正在由另一个 UIViewController 在代码中呈现。
我尝试使用 UIGestureRecognizer 来处理它,但不幸的是,这种方法似乎无法处理 UINavigationController 的控件(例如下一个按钮、返回等)。
【问题讨论】:
Xcode & Swift - Detecting user touch of UIView inside of UIScrollView的可能重复 我已经更新了我的问题。您发布的页面似乎对 UINavigationControllers 没有帮助。 【参考方案1】:您可以为此目的使用自己的UIWindow
子类,并通过几个UIResponder
方法之一跟踪用户活动:
[UIView hitTest:withEvent:]
[UIView touchesBegan:withEvent:]
[UIView touchesMoved:withEvent:]
[UIView touchesEnded:withEvent:]
任何父视图都可以跟踪子视图的触摸事件。例如,您可以将 UINavigationController
嵌入到跟踪父视图控制器中。
或者甚至通过添加到窗口将NonTouchableView
放在屏幕上:
[self.view.window addSubview:myNonTouchableView];
这是不可触摸视图的示例,它可以跟踪触摸事件的发生:
@interface NonTouchableView : UIView
@property (weak, nonatomic) id delegate;
@end
@implementation NonTouchableView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
// Report user activity to self.delegate
return nil;
@end
Swift 版本:
class NonTouchableView : UIView
weak var delegate: Object?
func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
// Report user activity to delegate
return nil
【讨论】:
我会在 Swift 中这样做吗?这种方法的问题是我不知道哪个视图控制器正在发送事件。所以在我的特殊情况下,我有一个由同一个导航控制器呈现的密码屏幕,当我使用密码屏幕时,hitTest 被触发,如果它是正在使用的密码屏幕,我不想重置计时器。 您应该在您想要跟踪的不同视图控制器的viewDidAppear
和viewDidDisappear
中动态添加和删除NonTouchableView
。您可以在公共父视图控制器 (TrackableViewController
) 中编写此代码一次。或者实现更复杂的逻辑,在层次结构中添加和删除此跟踪视图。
有没有办法在不继承 UINavigationController 的情况下做到这一点?我问的原因是因为 UINavigationController 在我无法访问的框架中。我所做的一切都是展示它,它收集并返回数据。
@u84six 是的,只需在需要跟踪时添加此视图,并在不需要时将其隐藏。或者您可以添加一次并使用hidden
属性启用/禁用它以轻松启动/停止跟踪。以上是关于如何使用 UINavigationController 中的所有视图和导航控制器的导航控件检测用户活动?的主要内容,如果未能解决你的问题,请参考以下文章
从 SwiftUI 推送到 UIViewController