在 UINavigationController 中未检测到 touchesBegan 和其他触摸事件

Posted

技术标签:

【中文标题】在 UINavigationController 中未检测到 touchesBegan 和其他触摸事件【英文标题】:touchesBegan and other touch events not getting detected in UINavigationController 【发布时间】:2010-06-14 16:36:43 【问题描述】:

简而言之,我想检测导航控制器标题栏上的触摸,但实际上根本无法捕捉到任何触摸!

一切都在没有 IB 的情况下完成,如果这有影响的话。

我的应用代理的 .m 文件包含:

MyViewController *viewController = [[MyViewController alloc] init];
navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
[window addSubview:navigationController.view];

在此窗口中添加了一些其他子视图,这些子视图覆盖了 navigationController,只留下了导航栏可见。

MyViewController 是 UIViewController 的子类,其 .m 文件包含:

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event  
 for (UITouch *touch in touches) 
  NSLog(@"ended\n");
  



-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

 for (UITouch *touch in touches) 
  NSLog(@"began\n");
  

我也尝试将这些函数直接放入应用代理的 .m 文件中,但控制台仍为空白。

我做错了什么?

【问题讨论】:

我的应用程序的整体设置是使用应用程序委托中的 [window addSubview:...] 按顺序添加到窗口的 UINavigationController、UIScrollView 和 UIPageControl。然后 ScrollView 包含更多具有应用程序实际内容的视图。 UINavigationController 的按钮工作正常,但没有检测到对标题的触摸。 touchesEnded 和 begin 是 UIView 方法而不是 UIViewController Daniel 是对的……这些永远不会在 UIViewController 中被调用。您需要使用这些方法创建一个 UIView 子类,然后将其分配给 viewController.view 或将其作为子视图添加到 viewController 的视图中(您可能会在 viewController 的 loadView 方法中执行这些操作。 我尝试分配一个自定义 viewController.view 但这似乎并没有在导航栏上进行触摸。如果我摆脱所有其他视图,只留下 navigationController 和其中的视图,它只会拾取视图内部的触摸,而不是栏。 @Daniel: touchesBegan/Ended 不是 UIView 方法,它们是 UIResponder 方法,而 UIViewController 是 UIResponder。 【参考方案1】:

好吧,由于没有更好的主意,我在我的应用程序中添加了另一个子视图,颜色清晰,以编程方式放置在导航栏标题上,并为该视图使用了一个自定义类,并覆盖了相关的触摸方法。工作正常,但我仍然希望有一个更优雅的解决方案。

【讨论】:

@Daniel 不,这样就完美了。如果我们遇到同样的问题,通过编辑将答案嵌入到问题中会使我们更难找到解决方案。【参考方案2】:

视图控制器被插入到其托管视图和父视图之间的响应者链中:

因为视图控制器与它们管理的视图紧密绑定,它们也是用于处理事件的响应者链的一部分。视图控制器本身是 UIResponder 类的后代,并被插入到托管视图与其父视图之间的响应者链中。因此,如果视图控制器管理的视图不处理事件,它会将事件传递给其视图控制器,然后视图控制器可以选择处理事件或将其转发给视图的父视图。

(UIViewController documentation)

是否有可能,您的控制器的托管视图正在吞噬所有事件?是什么样的景色?

【讨论】:

我对此相当陌生,对整个视图/控制器关系并不熟悉,但就我而言,MyViewController 中的视图实际上是空白的。我只是尝试制作一个自定义 UIView 子类并从那里覆盖 touches 方法,然后将该子类用于该控制器的视图,但这也不起作用。这个 MyViewController 的唯一目的是提供一个带有按钮和标题的导航栏。【参考方案3】:

遇到了麻烦,因为我的自定义视图在视图层次结构中更深。相反,我爬上了响应者链,直到找到UIViewController

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
    // Pass to top of chain
    UIResponder *responder = self;
    while (responder.nextResponder != nil)
        responder = responder.nextResponder;
        if ([responder isKindOfClass:[UIViewController class]]) 
            // Got ViewController
            break;
        
    
    [responder touchesBegan:touches withEvent:event];

【讨论】:

【参考方案4】:

尝试将方法 userInteractionEnabled = YES 添加到您的 UIImageView

【讨论】:

感谢您禁用触摸的逻辑。【参考方案5】:

这些方法应该放在 UIView 子类而不是 UIViewControllers...UIView 将接收触摸回调,然后你可以在 UIView 上制定一个协议并在 UIViewController 上实现它,这样 UIViewController 就会收到一些回调当触摸事件发生时......这是一个讨论协议以及如何定义和实现它们的链接Protocols Ref

【讨论】:

以上是关于在 UINavigationController 中未检测到 touchesBegan 和其他触摸事件的主要内容,如果未能解决你的问题,请参考以下文章

在 UINavigationController 内的 UITabBarcontroller 中添加 UINavigationController?

从嵌入在 UINavigationController 中的一个视图控制器到另一个 UINavigationController

(Swift) 在嵌套在 Main UINavigationController 中的 UINavigationController 和 UITabController 之间切换

关闭 UINavigationController 并呈现另一个 UINavigationController

带有主 UINavigationController 和详细 UINavigationController 的 UISplitViewcontroller

UINavigationController 标题和按钮