Cocoa touch UIView--“;启用用户交互”功能;父母为假,孩子为真?

Cocoa touch UIView--“;启用用户交互”功能;父母为假,孩子为真?,cocoa-touch,ios,uiview,Cocoa Touch,Ios,Uiview,父视图上的userInteractionEnabled=NO可能会阻止所有子视图上的用户交互。这是正确的吗?有什么办法可以解决这个问题吗?没错,父视图上的userInteractionEnabled设置为“否”将级联到所有子视图。如果需要某些子视图启用交互,但不需要其他子视图,您可以将子视图分为两个父视图:一个为userInteractionEnabled=YES,另一个为NO。然后将这两个父视图放在主视图中。您可以将UIView子类化并覆盖hitTest:withEvent:以将触摸事件传递给

父视图上的userInteractionEnabled=NO可能会阻止所有子视图上的用户交互。这是正确的吗?有什么办法可以解决这个问题吗?

没错,父视图上的userInteractionEnabled设置为“否”将级联到所有子视图。如果需要某些子视图启用交互,但不需要其他子视图,您可以将子视图分为两个父视图:一个为userInteractionEnabled=YES,另一个为NO。然后将这两个父视图放在主视图中。

您可以将UIView子类化并覆盖hitTest:withEvent:以将触摸事件传递给您指定的视图(\u backView):

如果触摸事件由该视图处理,它将被传递到“_backView”(可以是IBOutlet,以便使用interface builder进行设置);如果要由任何子视图处理,只需返回该子视图(超级hitTest:PointWithEvent:event的结果);)

只要您知道需要将事件传递给哪个视图,这个解决方案就可以了;此外,我不知道它是否有问题,因为我们返回的视图(\u backView)不是当前UIView的子视图!!但对我来说效果很好

更好的解决方案可能是中提到的解决方案
这里提到使用
-pointInside:withEvent:
;与以前的解决方案相比,它的优点是不需要指定“\u backView”来接收事件(事件只需传递到链中的下一个视图)!缺点可能是我们需要在所有子视图上执行
-pointInside:withEvent:
(虽然开销可能可以忽略不计)

我遇到了一个奇怪的情况。我有一个UIView(称之为V),它有一个UIButton作为子视图。调用此UIButton,button X。下面是我用于按钮X的目标/选择器的方法。下面的self是视图V。发送方参数是button X

导致我出现问题的情况是,如果我触摸UI上的另一个按钮(在导航栏上,称此按钮为Y),然后快速触摸按钮X,其中按钮Y操作禁用视图V,我仍然会将触摸事件发送到按钮X

- (void) buttonAction: (UIButton *) sender
{
    NSLog(@"superview: %d", sender.superview.userInteractionEnabled);  
    NSLog(@"button itself: %d", sender.userInteractionEnabled);

    // <snip>
}
-(无效)按钮操作:(UIButton*)发送者
{
NSLog(@“superview:%d”,sender.superview.userInteractionEnabled);
NSLog(@“按钮本身:%d”,sender.userInteractionEnabled);
// 
}
以下是输出:

2014-12-19 16:57:53.826 MyApp[6161:960615]超级视图:0
2014-12-19 16:57:53.826 MyApp[6161:960615]按钮本身:1

也就是说,发生了按钮操作,并且按钮的superview禁用了用户交互!而且子视图仍然启用了用户交互

对于那些认为这似乎是人为的人来说,在我的应用程序的UI上,在iPad上运行(运行iOS 8.1.2),这是我在使用应用程序时偶然想到的。这不是我最初想要创造的东西

想法

下面给出了我当前的解决方法,但它的必要性似乎真的很奇怪

- (void) buttonAction: (id) sender
{
    NSLog(@"superview: %d", sender.superview.userInteractionEnabled);  
    NSLog(@"button itself: %d", sender.userInteractionEnabled);
    if (! self.userInteractionEnabled) return;

    // <snip>
}
-(void)按钮操作:(id)发送者
{
NSLog(@“superview:%d”,sender.superview.userInteractionEnabled);
NSLog(@“按钮本身:%d”,sender.userInteractionEnabled);
如果(!self.userInteractionEnabled)返回;
// 
}

我在我的“自定义警报控制器”视图的xib中执行此操作


我为此想出了一个奇怪的解决方案,我在tableView单元格中有一个子视图,我希望它可以触摸,但父视图不应该

以上两种解决方案都不适用于我,但我找到了另一种解决方案。 转到情节提要,将TapGestureRecognitor添加到父视图中,以吸收父视图上的接触。 问题解决了

这是解决方案 创建从“UIView”继承的类,并编写重写“inside point”的func


然后在storyboard或xib中,superview必须使用这个类

谢谢懒人。我的想法是使用透明视图来管理少数相关弹出菜单类型视图的布局。但是,如果看不见的布局视图阻止了与它下面的东西的交互,这对我来说就不起作用了。Hrrmmmm…是的,透明视图的想法在这种情况下不起作用。可以直接将子视图添加到父视图中吗?可以。在任何情况下,最好使用半透明背景。没什么大不了的。我想知道是否各种触摸开始了:父视图中的处理程序可以实现为只说“我不想要这个事件,请将它传递给我下面的人”@orion您当然可以这样做,但它不会有用,因为iOS中的触摸会从子视图到父视图。如果父视图收到触摸,则表示子视图已忽略它。感谢此处的方法和“禁用触摸…”链接。这里描述的方法看起来很干净。hitTest太晚了。。。这是最好的答案。。。是的,就是这样,这完全是愚蠢的,就像iOS中的许多东西一样,苹果制作简单API的日子在哪里?我想那大概是20年前的事了,现在API是哲学家写的。当他们不忙着写堆栈溢出注释时。最佳答案的可能副本在这里。。。
- (void) buttonAction: (id) sender
{
    NSLog(@"superview: %d", sender.superview.userInteractionEnabled);  
    NSLog(@"button itself: %d", sender.userInteractionEnabled);
    if (! self.userInteractionEnabled) return;

    // <snip>
}
for (UIView *subview in self.superview.subviews) {

    if (![subview isEqual:self]) {
        subview.userInteractionEnabled = NO;
    }
}
class TTSView: UIView {


    
    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
          for view in self.subviews {
               if view.isUserInteractionEnabled, view.point(inside: self.convert(point, to: view), with: event) {
                   return true
               }
           }

           return false
     }

}