SkylerHill-Sky
SkylerHill-Sky

Reputation: 2196

While button is being pressed

How do i set up a button (IBAction and UIButton attached) to continue to run the IBAction or a function while the button is being pressed, running a functioning continuously until the button is let up.

Should i attach a value changed receiver?

Simple question, but I can't find the answer.

Upvotes: 0

Views: 1732

Answers (3)

Jody Hagins
Jody Hagins

Reputation: 28349

Add a dispatch source iVar to your controller...

dispatch_source_t     _timer;

Then, in your touchDown action, create the timer that fires every so many seconds. You will do your repeating work in there.

If all your work happens in UI, then set queue to be

dispatch_queue_t queue = dispatch_get_main_queue();

and then the timer will run on the main thread.

- (IBAction)touchDown:(id)sender {
    if (!_timer) {
        dispatch_queue_t queue = dispatch_get_global_queue(
            DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
        // This is the number of seconds between each firing of the timer
        float timeoutInSeconds = 0.25;
        dispatch_source_set_timer(
            _timer,
            dispatch_time(DISPATCH_TIME_NOW, timeoutInSeconds * NSEC_PER_SEC),
            timeoutInSeconds * NSEC_PER_SEC,
            0.10 * NSEC_PER_SEC);
        dispatch_source_set_event_handler(_timer, ^{
            // ***** LOOK HERE *****
            // This block will execute every time the timer fires.
            // Do any non-UI related work here so as not to block the main thread
            dispatch_async(dispatch_get_main_queue(), ^{
                // Do UI work on main thread
                NSLog(@"Look, Mom, I'm doing some work");
            });
        });
    }

    dispatch_resume(_timer);
}

Now, make sure to register for both touch-up-inside and touch-up-outside

- (IBAction)touchUp:(id)sender {
    if (_timer) {
        dispatch_suspend(_timer);
    }
}

Make sure you destroy the timer

- (void)dealloc {
    if (_timer) {
        dispatch_source_cancel(_timer);
        dispatch_release(_timer);
        _timer = NULL;
    }
}

Upvotes: 2

Mick MacCallum
Mick MacCallum

Reputation: 130193

[myButton addTarget:self action:@selector(buttonIsDown) forControlEvents:UIControlEventTouchDown];
[myButton addTarget:self action:@selector(buttonWasReleased) forControlEvents:UIControlEventTouchUpInside];


- (void)buttonIsDown
{
     //myTimer should be declared in your header file so it can be used in both of these actions.
     NSTimer *myTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(myRepeatingAction) userInfo:nil repeats:YES];
}

- (void)buttonWasReleased
{
     [myTimer invalidate];
     myTimer = nil;
}

Upvotes: 3

wczekalski
wczekalski

Reputation: 745

UIButton should call a starting method with touchDown event and call ending method with touchUpInside event

Upvotes: 0

Related Questions