【问题标题】:UIControl Not Receiving TouchesUIControl 不接收触摸
【发布时间】:2012-03-10 03:20:17
【问题描述】:

我有一个 UIControl 实现 touches started 方法,如下所示:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];
    //More code goes here

UIControl 的这个子类在视图控制器中实例化,然后作为子视图添加到该视图控制器。我在 UIControl 的 touches started 方法上有一个断点,并且该方法永远不会被调用。我一直在做一些阅读,似乎视图控制器有一些逻辑来决定是否将触摸事件传递给它的子视图。奇怪的是,我在同一个视图控制器中有一个不同的 UIControl 子类,当用户触摸它时,触摸事件会传递给它! 完整代码如下:

.h

#import <UIKit/UIKit.h>

@interface CustomSegment : UIView
@property (nonatomic, strong) UIImageView *bgImageView;
@property (nonatomic, assign) NSInteger segments;
@property (nonatomic, strong) NSArray *touchDownImages;
@property (nonatomic, readonly, assign) NSInteger selectedIndex;
@property (nonatomic, weak) id delegate;


- (id)initWithPoint:(CGPoint)point numberOfSegments:(NSInteger)_segments andTouchDownImages:(NSArray *)_touchDownImages;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
@end

.m

#import "CustomSegment.h"

@implementation CustomSegment
@synthesize bgImageView, segments, touchDownImages, selectedIndex, delegate;

- (id)initWithPoint:(CGPoint)point
   numberOfSegments:(NSInteger)_segments
           andTouchDownImages:(NSArray *)_touchDownImages  
{  
    self = [super initWithFrame:CGRectMake(point.x, point.y, [[_touchDownImages     objectAtIndex:0] size].width, [[touchDownImages objectAtIndex:0] size].height)];
if (self)
{
    touchDownImages = _touchDownImages;
    segments = _segments;
    bgImageView = [[UIImageView alloc] initWithImage:[touchDownImages objectAtIndex:0]];
    [self addSubview:bgImageView];
}
return self;
}

- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
{
    return YES;  
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //[super touchesBegan:touches withEvent:event];
    UITouch *touch = [touches anyObject];
    float widthOfSegment = [self frame].size.width / segments;
    float bottomPoint = 0;
    float topPoint = widthOfSegment;
    for (int i = 0; i < segments; i++)
    {
        if ([touch locationInView:self].x > bottomPoint && [touch locationInView:self].x < topPoint)
        {
            [bgImageView setImage:[touchDownImages objectAtIndex:i]];
            selectedIndex = i;
            return;
        }
        else
        {
            bottomPoint = topPoint;
            topPoint += topPoint;
        }
    }
}
@end

【问题讨论】:

标签: iphone ios uitouch uicontrol


【解决方案1】:

可能是另一个视图覆盖了您的 UIControl,并阻止它接收触摸事件。另一种可能性是 userInteractionEnabled 被错误地设置为 NO

编辑:我看到您在上面添加了更多代码。您是否确认您的视图框架的宽度和高度大于零?在我看来,您直接在 NSArray 的对象(即“id”)上调用“size”。我不知道如果没有演员表你是如何做到这一点的(也许上面的括号没有出现?)但如果你以某种方式把它拉下来,如果它是一个无效的值,我不会感到惊讶。

【讨论】:

  • 没有任何东西覆盖它,并且 userInteractionEnables 没有在任何地方设置为 NO。感谢您的建议
【解决方案2】:

可能性:

  • 您可能忘记为 UIControl 设置委托。
  • 接收触摸的另一个 UIControl 正在遮挡/覆盖 UIControl。

【讨论】:

  • 谢谢,我认为我不需要 UIControl 的委托。也许我不清楚,但开始的接触是在我的 UIControl 子类中。我之前考虑过一些涵盖它的东西,但事实并非如此,不过谢谢
【解决方案3】:

检查所有父视图的frames。规则是如果视图的子视图(或其部分)在视图边界之外,它不会接收到触摸事件。

【讨论】:

  • 感谢 ivanzoid,视图控制器(UIControl 的父级)框架是整个屏幕,所以这应该不是问题。特别是因为 UIControl 非常小。不过还是谢谢
【解决方案4】:

首先,你为什么打电话给[super touchesBegan:touches withEvent:event];?此调用将事件转发给下一个响应者。通常你只在你不想处理事件时才这样做。你确定你知道你在那里做什么?

一个想法为什么它不起作用 - 是不是你有一个手势识别器首先处理事件?

不管怎样,你真的需要覆盖touchesBegan吗? UIControl 用于自行跟踪触摸事件并调用您的处理程序作为响应。 UIControl 文档说如何子类化它。

子类化注释

您可能出于以下两个原因想要扩展 UIControl 子类:

  • 观察或修改针对特定事件向目标发送操作消息

    为此,请覆盖 sendAction:to:forEvent:,评估传入的选择器、目标对象或 UIControlEvents 位掩码,然后按要求继续。

  • 提供自定义跟踪行为(例如,更改突出显示的外观)

    为此,请覆盖以下一个或所有方法:beginTrackingWithTouch:withEvent:、continueTrackingWithTouch:withEvent:、endTrackingWithTouch:withEvent:。

【讨论】:

  • 谢谢 Sulthan,我同意我不应该打电话给 super。没有手势识别器,我尝试使用 begintrackingtouch 而不是 touchs started 只是为了得到相同的结果。我对此感到非常奇怪的是,我有一个不同的 UIControl 可以正常工作,并且我确保我以相同的方式处理触摸。然而,它仍然不起作用。
  • 另一个想法 - 它在 UIScrollView 内,它取消了对其内容的触摸?有很多可能性。
  • 为了使事情更简单,我创建了一个空白应用程序,其中包含一个空 vc,我唯一放入其中的是控件。还是一样的问题。这非常令人沮丧,但感谢您的所有帮助。
  • 在这一点上,我不妨编辑原始帖子并在上面添加代码
  • 您应该始终在 UIControl 子类中的触摸处理方法上调用“Super”,否则它的触摸跟踪方法将不会触发。
【解决方案5】:

tl;dr 将 UIControl 的所有子视图设置为 setUserInteractionEnabled:NO。 UIImageViews 默认设置为NO

原帖

我最近发现的一件事是,如果 UIControl 的最顶层子视图有setUserInteractionEnabled:NO,它会有所帮助。我到达这里是因为我有一个带有 UIImageView 的 UIControl 子类,因为它只是子视图并且工作正常。 UIImageView 默认将userInteractionEnabled 设置为NO

我还有另一个带有 UIView 的 UIControl,因为它是最顶层的子视图(技术上相同的 UIControl 处于不同的状态)。我相信 UIView 默认为 userInteractionEnabled == YES,这排除了 UIControl 正在处理的事件。将 UIView 的 userInteractionEnabled 设置为 NO 解决了我的问题。

我不知道这里是不是同样的问题,但也许这会有所帮助?

-- 编辑:当我说最顶层视图时...可能将 UIControl 的所有子视图设置为 setUserInteractionEnabled:NO

【讨论】:

  • 已经3年多了。凯尔应该接受这个答案!
  • 啊,这让我发疯了,然后我看到了你的答案,并尝试在其中一个子视图之外点击它,它起作用了。谢谢!
  • 应该被接受的答案,确保顶视图没有用户交互修复它。谢谢
  • 男人!我已经用头撞墙了几个小时,已经试图理解为什么我的自定义 UIControl 没有接收到事件!太感谢了!!! ?
【解决方案6】:

很公平。最近重新调查了这一点(UIControl 的文档记录很差)并意识到跟踪触摸是 touchesBegan/Ended 的替代品,而不是额外的,对此感到抱歉。我会推翻投票,但它不会让我:(

【讨论】:

    【解决方案7】:

    UIView 实例无法响应事件,因此根据您当前的配置无法触发您的操作方法?

    尝试将视图的类更改为 UIControl 类的实例!

    【讨论】:

      【解决方案8】:

      您可能需要在 UIControl 子类中覆盖 intrinsicContentSize

      override var intrinsicContentSize: CGSize {
          return CGSize(width: 150, height: 100)
      }
      

      我不太明白它是如何修复它或为什么,但它确实有效。它甚至不需要和你控制的一样大小。

      【讨论】:

        【解决方案9】:

        Xcode 12 及更高版本。

        • 如已接受的答案中所述,请确保 UIControl 视图未选中“启用用户交互”。
        • 选择您的 UIControl 视图并切换到“Connection Inspector”并制作 确保它已连接到“Touch Up Inside”事件。有时 Xcode 使用“Value Changed”事件,因此请确保更改为“Touch Up Inside”活动

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-12-03
          • 2015-11-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多