28

我有一个 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
4

9 回答 9

105

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

原帖

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

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

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

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

于 2012-05-16T14:41:27.297 回答
2

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

于 2012-02-19T15:26:54.810 回答
1

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

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

于 2012-02-19T14:38:06.863 回答
1

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

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

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

子类化注释

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

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

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

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

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

于 2012-02-19T20:00:45.597 回答
1

Xcode 12 及更高版本。

  • 正如接受的答案中提到的,确保 UIControl 视图的所有子视图都未选中“启用用户交互”。
  • 选择您的 UIControl 视图并切换到“Connection Inspector”并确保它已连接到“Touch Up Inside”事件。有时 Xcode 使用“Value Changed”事件,因此请确保更改为“Touch Up Inside”事件
于 2021-01-13T23:52:12.637 回答
0

可能性:

  • 您可能忘记为 UIControl 设置委托。
  • 接收触摸的另一个 UIControl 正在遮挡/覆盖 UIControl。
于 2012-02-19T15:07:11.040 回答
0

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

于 2012-07-08T18:59:54.257 回答
0

您可能需要intrinsicContentSizeUIControl子类中覆盖。

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

我不太明白它如何修复它或为什么,但它有效。它甚至不需要与您控制的精确尺寸相同。

于 2020-04-21T02:21:54.640 回答
-2

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

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

于 2012-11-15T08:32:06.600 回答