如何调试谁在UIKit吃我的触摸?

时间:2014-09-29 21:13:41

标签: ios

我无法弄清楚为什么在我的视图中点击文本字段和按钮不起作用。我已经检查了所有明显的事情,例如userInteractionEnabled是否设置为YES,是否安装了手势识别器,以及前景中是否有不可见的视图。

iOS中是否有最佳实践,可以在首次显示触摸时将其触摸到消耗的位置?

更新:

这两个答案都很有帮助。在我的调查过程中,我了解到如果子视图超出其父级边界,即使父级不是剪辑子视图,子视图也不会接收事件。我从文本字段中打印出了没有触及的超视图链,我看到其中一个视图的高度为0.我设置了一些约束来拉伸它,我的问题就解决了。

7 个答案:

答案 0 :(得分:19)

您可以继承UIWindow并覆盖-[UIWindow sendEvent]:,然后在调用它时,使用-[UIWindow hitTest:withEvent:]来测试哪个视图将接收该事件。

然后,您可以调用-[UIView recursiveDescription]打印一些调试信息,以帮助您了解该视图收到触摸事件的原因。

完成后请记得致电[super sendEvent:]


对于那些使用Storyboard并想知道如何更改主应用程序窗口类的人:

class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow? = TestWindow()
    // ....
}

只需提供AppDelegate' s window var的默认值。当应用程序启动时,UIApplicationMain将实例化一个代理并向其询问window。如果windownil,则会自动创建新的{{1}}。但是如果我们在这里提供默认值,它将在整个应用程序中使用。

答案 1 :(得分:5)

不是问题的直接答案,但触摸消失的一个非常常见的原因是控件位于一个尺寸小于控件的uiview中,但是没有削减它的界限,所以你不会看到父视图较小(甚至可能是零大小)。

Parent UIView size=0x0, clipToBounds=false

   Child UIButton size=100x50

=>儿童按钮不会获​​得任何触摸事件。

答案 2 :(得分:4)

您可以使用新的Xcode6实时视图调试,通过在3D中转换视图层次结构,您可以看到哪些视图高于您关注的视图并进行检查。

答案 3 :(得分:1)

我的完整 Swift 示例(来自@Bryan Chen和@kelin答案...

TableA
empid,other
1,A
1,B
1,C

TableB
empid,other
1,Y
1,Z

SELECT * FROM A INNER JOIN B ON a.empid=b.empid

答案 4 :(得分:0)

您可以使用符号断点来调试它:

-[UIWindow sendEvent:]po $arg3

enter image description here 日志:

<UITouchesEvent: 0x6000026fa6d0> timestamp: 179462 touches: {(
<UITouch: 0x7f84d6f10380> phase: Began tap count: 1 force: 0.000 
window: <UIWindow: 0x7f84d6d0ad10; frame = (0 0; 375 812); autoresize = W+H; 
gestureRecognizers = <NSArray: 0x600001aa8870>; layer = <UIWindowLayer: 0x6000014bd7e0>> view: <UIView: 0x7f84d6d0bff0; frame = (0 0; 375 812); 
autoresize = W+H; layer = <CALayer: 0x6000014bdc60>> location in window: {165.66665649414062, 232.33332824707031} previous location in window: 
{165.66665649414062, 232.33332824707031} location in view: {165.66665649414062, 
232.33332824707031} previous location in view: {165.66665649414062,232.33332824707031}
)}

答案 5 :(得分:0)

查看消耗触摸事件的一种基本方法是简单地添加调试视图并覆盖hitTest(:event:)方法。将此类附加到故事板上的视图中。

class DebugView: UIView {
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let view = super.hitTest(point, with: event)
        print("View")
        print(view)
        return view
    }
}

将其附加到控制器的根视图将使您可以访问使用touch事件的视图。请注意,每次触摸事件,hitTest方法都会被调用两次。

答案 6 :(得分:0)

要从@Peter的答案中了解有关哪种姿势识别器是问题的更多详细信息,我打印出了一系列的motionRecognizer:

class TestWindow:UIWindow {
    override func sendEvent(_ event: UIEvent) {

        event.allTouches?.forEach() { touch in
            print("touch")
            print(touch.gestureRecognizers ?? "")
            /// [<UILongPressGestureRecognizer: 0x7fb205964ab0; state = Possible; view = <UIView 0x7fb205964940>; target= <(action=_handleMenuGesture: ....
        }

        super.sendEvent(event)
    }
}