UIControl子类 – 事件调用两次

我目前正在开发一个自定义的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; } } 

这按预期工作,@“开始”是一次性的。 下一步是我用UIControlEventTouchDown添加一个Target和一个Selector。

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

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

桑德罗梅尔

一旦调用,事件调度程序将自动发生对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, eg removed from window 

还有tracking实例变量。

所以我认为你不应该发布事件或听事件。 此外,如果它不在您的视图中,它是否真的可以获得beginTrackingWithTouch事件? 看起来不像。 因此,我认为您不需要进行测试,看看它是否在您的视野中。

因此,我认为可能值得退一步思考您正在尝试做什么并重新阅读UIControl文档。 特别:

子类注释您可能希望扩展UIControl子类有以下两个原因:

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

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

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

第二部分听起来更像是你想要做的事情 – 你的UIControl子类中的自定义跟踪。

嗯..检查我的代码你的目标:

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"); }