4
votes

I am trying to figure out how to log the UIControlEvents so that I can see exactly which ones I want to add to my UIButton.

I can't seem to figure it out. Here is what I've tried so far:

[button addTarget:self action:@selector(buttonTouched:forEvent:) forControlEvents:UIControlEventAllEvents];


-(void)buttonTouched:(UIButton *)button forEvent:(UIControlEvents)event{

NSLog(@"%s", __PRETTY_FUNCTION__);

switch (event) {
    case UIControlEventTouchDown:
        NSLog(@"UIControlEventTouchDown");
        break;
    case UIControlEventTouchDownRepeat:
        NSLog(@"UIControlEventTouchDownRepeat");
        break;
    case UIControlEventTouchDragInside:
        NSLog(@"UIControlEventTouchDragInside");
        break;
    case UIControlEventTouchDragOutside:
        NSLog(@"UIControlEventTouchDragOutside");
        break;
    case UIControlEventTouchDragEnter:
        NSLog(@"UIControlEventTouchDragEnter");
        break;
    case UIControlEventTouchDragExit:
        NSLog(@"UIControlEventTouchDragExit");
        break;
    case UIControlEventTouchUpInside:
        NSLog(@"UIControlEventTouchUpInside");
        break;
    case UIControlEventTouchUpOutside:
        NSLog(@"UIControlEventTouchUpOutside");
        break;
    case UIControlEventTouchCancel:
        NSLog(@"UIControlEventTouchCancel");
        break;
    case UIControlEventValueChanged:
        NSLog(@"UIControlEventValueChanged");
    default:
        break;
}
}

The only log that is printed is the __PRETTY_FUNCTION__ log. I also tried this, just in case the switch statement was the problem:

if (event == UIControlEventTouchDown) {
    NSLog(@"UIControlEventTouchDown");
}
if (event == UIControlEventTouchDownRepeat){
    NSLog(@"UIControlEventTouchDownRepeat");
}
etc...

Still nothing logs. What am I doing wrong?

Edit: I experimented further by changing which event I add to the button like so:

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

And then I logged the input very specifically:

-(void)buttonTouched:(UIButton *)button forEvent:(UIControlEvents)event{

    NSLog(@"UIControlEventTouchDown = %i", UIControlEventTouchDown);
    NSLog(@"event = %i", event);
}

Here is the output:

UIControlEventTouchDown = 1
event = 350486320

Does anyone have any idea what is going on?

Edit 2: Thanks to TAKeanice I now realize that I hadn't written the selector correctly. I'm not sure exactly what the log for event was printing out, but while I had essentially cast a UIEvent as an enum type (UIControlEvents) it still was giving a value in the log. Anyhow, it seems to me that there must still be a way to find out what the UIControlEvents is, but I can't see how from the documentation. However, Apple alludes to it in the UIControl documentation:

Subclassing Notes You may want to extend a UIControl subclass for either of two reasons:

To observe or modify the dispatch of action messages to targets for particular events To do this, override sendAction:to:forEvent:, evaluate the passed-in selector, target object, or UIControlEvents bit mask, and proceed as required.

To provide custom tracking behavior (for example, to change the highlight appearance) To do this, override one or all of the following methods: beginTrackingWithTouch:withEvent:, continueTrackingWithTouch:withEvent:, endTrackingWithTouch:withEvent:

How can you evaluate the UIControlEvents bit mask when the argument passed in for sendAction:to:forEvent: is UIEvent? Any ideas?

2
If you put a breakpoint at the beginning of your switch statement, does event have a value?Wyatt Page
@WyattPage The problem isn't that the event has no value. The problem is that the value doesn't correspond to any of the UIControlEventTouch…etc. I don't understand why this is.daveMac
@daveMac check my updated answerBasheer_CAD

2 Answers

2
votes

Try this out:

// somewhere
[self.btn addTarget:self action:@selector(buttonTouched:forEvent:) forControlEvents:UIControlEventAllEvents];


- (void)buttonTouched:(UIButton*)sender forEvent:(id)event {
    NSSet *touches = [event allTouches];
    UITouch *touch = [touches anyObject];
    UITouchPhase phase = touch.phase;
}

UPDATE:
you will get touches, then in the last touch you will have phase, which indicates what is this event

EXPLANATION:

From the position of the touch and the phase you will be able to compute the event:

  • UITouchPhaseEnded + touch location is within bounds => UITouchUpInside
  • UITouchPhaseEnded + touch location is outside bounds => UITouchUpOutside
  • ...
1
votes

You don´t receive the "UIControlEvent" but the "UIEvent" in the event parameter, which is an entirely different class.

The Documentation says: The UIEvent is of some type. Those can be any of the UIEventType enumeration, which are

  • UIEventTypeTouches
  • UIEventTypeMotion
  • UIEventTypeRemoteControl

The event can also have a subtype, those seem to be related only to the remoteControl type.

https://developer.apple.com/library/ios/documentation/uikit/reference/UIEvent_Class/Reference/Reference.html

So, you won´t find the exact ControlEventType in the event parameter, but only the "general" type of action, to which the control responded.

Seems that the only option for you is to trigger different methods for different UIControlEvents.

----edit----
Another option would be to implement UIControl yourself, so that you can figure out exactly where the user touches when and with how many fingers etc.