UIControl Subclass - события, вызываемые дважды - PullRequest
3 голосов
/ 14 июля 2011

В настоящее время я работаю над пользовательским подклассом 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;
 }  
}

Это работает, как ожидалось, и @ "Пуск" регистрируется точно один раз.Следующим шагом является добавление Target и Selector с помощью UIControlEventTouchDown.

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

Это также работает, и вызывается действие: метод.Но это моя проблема.Действие вызывается дважды.Что я делаю неправильно?Я просто использую [self sendActionsForControlEvents:UIControlEventTouchDown]; один раз, и целевое действие вызывается дважды.Что не так с моим кодом?

Сандро Мейер

Ответы [ 2 ]

11 голосов
/ 16 июля 2011

Первый вызов метода действия происходит автоматически диспетчером событий после того, как вы позвонили:

[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.

0 голосов
/ 14 июля 2011

Хм .. Проверьте мой код для ваших целей:

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