4

我目前正在开发一个自定义 UIControl 子类。要跟踪触摸,我使用以下方法:

- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
 NSLog(@"Start");
 CGPoint location = [touch locationInView:self];
 if ([self touchIsInside:location] == YES) {
    //Touch Down
    [self sendActionsForControlEvents:UIControlEventTouchDown];
    return YES;
 }
 else {
    return NO;
 }  
}

这可以按预期工作,并且 @"Start" 只记录一次。下一步是使用 UIControlEventTouchDown 添加一个 Target 和一个 Selector。

[markItem addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside];

这也有效,并且调用了 action: 方法。但这是我的问题。该动作被调用两次。我究竟做错了什么?我只使用[self sendActionsForControlEvents:UIControlEventTouchDown];一次,目标操作被调用两次。我的代码有什么问题?

桑德罗·迈耶

4

3 回答 3

11

调用后,事件调度程序会自动调用 action 方法:

[markItem addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside];

注册处理程序。

所以当你打电话时:

//Touch Down
[self sendActionsForControlEvents:UIControlEventTouchDown];

您正在生成对您的处理程序(以及任何其他已连接的)的第二次调用。

因此,您似乎不需要动作处理程序和 beginTracking - 使用其中一个。

更新:

鉴于您的评论和进一步的思考:由于您是 UIControl 的子类,我认为您可能不想为自己注册事件处理程序。

相反,您应该专门使用:

- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event;
- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event;
- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event;
- (void)cancelTrackingWithEvent:(UIEvent *)event;   // event may be nil if cancelled for non-event reasons, e.g. removed from window

也是tracking实例变量。

所以我认为你不应该发布事件或收听事件。此外,如果 beginTrackingWithTouch 事件不在您的视图中,是否真的有可能获得它?似乎不会。所以我认为你不需要测试来看看它是否在你的视野中。

所以我认为可能值得退后一步,想想你正在尝试做什么并重新阅读 UIControl 文档。具体来说:

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

观察或修改针对特定事件向目标分配操作消息为此,请覆盖sendAction:to:forEvent:、评估传入的选择器、目标对象或UIControlEvents位掩码,然后根据需要继续操作。

提供自定义跟踪行为(例如,更改突出显示外观)为此,请覆盖以下一个或所有方法:beginTrackingWithTouch:withEvent:continueTrackingWithTouch:withEvent:endTrackingWithTouch:withEvent:

第一部分是让您的UIControl子类为您的控件的客户端或用户执行目标操作处理的非标准处理(这听起来不像您正在尝试做的事情,尽管您并没有真正给出高级描述)。

第二部分听起来更像您想要做的 - 在您的UIControl子类中自定义跟踪。

于 2011-07-15T22:46:26.373 回答
0

我也有同样的问题。当我注册一个动作时

[button addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchDown];

动作方法将被触发一次,但是当我注册它时

[button addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside];

动作方法将被触发两次。

为我解决的问题是确保我的- (void) action:方法返回IBAction而不是void. 我不确定为什么这似乎可以解决它。

于 2022-03-04T19:07:19.043 回答
-1

嗯..检查我的代码是否符合您的目标:

UIContr.h

@interface UIContr : UIControl {

}

@end

UIContr.m

#import "UIContr.h"
@implementation UIContr
- (id)initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code.
    }
    return self;
}

- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
    NSLog(@"Start");
    CGPoint location = [touch locationInView:self];
    if (CGRectContainsPoint(self.frame, location)) {
        //Touch Down
        [self sendActionsForControlEvents:UIControlEventTouchDown];
        return YES;
    }
    else {
        return NO;
    }  
}

- (void)dealloc {
    [super dealloc];
}
@end

如何在 UIViewController 中使用:

- (void)viewDidLoad {
    UIContr *c = [[UIContr alloc] initWithFrame:CGRectMake(20, 20, 100, 100)];
    [c addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside];
    c.backgroundColor = [UIColor redColor];
    [self.view addSubview:c];
}

-(void)action:(id)sender{
    NSLog(@"123");
}
于 2011-07-14T08:22:35.830 回答