Julia Green
Julia Green

Reputation: 55

How to preform an action while the button is pressed?

I have a button and i need to change the label while the button is pressed to @"PRESSED" and if it's let go I need to change it to @"LET GO". I've found many answers, but i have no idea how to implement them in Xcode 5. That are the ones i tried:

You can start your action on the touchDownInside and stop it on the touchUpInside actions - you can hook them up in IB.

or

Add targets to your button for both control states, UIControlEventTouchDown and UIControlEventTouchUpInside or UIControlEventTouchUpOutside

or even

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

I am new to iOS and have no idea whatsoever how to do any of that! Thanks a lot for any help in advance!

Upvotes: 1

Views: 377

Answers (3)

Michael
Michael

Reputation: 1107

If you are new to xCode this can be difficult to understand. Follow this and you'll be allright.

  • Go to Storyboard and put a button in the view now go to the Inspector and change State config from Default to Highlighted

highloghted

  • In placeholder 'highlighted title' put 'Pressed'

placeholder

pressed title

  • Now click on the Assistant Editor to open the .m file next to Storyboard

enter image description here

  • CNTRL + Click and drag from the Button to the .m file code to create a TouchUpInside event, mine called buttonPressed

event

  • Put this code in the method body and you are good to go!

methodbody

This is what it will look like, pressed and released:

pressed

letgo

Upvotes: 0

Zhang
Zhang

Reputation: 11607

The first method does what you want, here's an example implementation:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    UIButton *myButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.bounds.size.width / 2.0 - 50.0, self.view.bounds.size.height / 2.0 - 25.0, 100.0, 50.0)];
    myButton.backgroundColor = [UIColor colorWithRed:0.2 green:0.3 blue:0.8 alpha:1.0];
    [myButton setTitle:@"PRESS ME" forState:UIControlStateNormal];
    [myButton addTarget:self action:@selector(setPressed:) forControlEvents:UIControlEventTouchDown];
    [myButton addTarget:self action:@selector(setLetGo:) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:myButton];
}

-(void)setPressed:(id)sender
{
    UIButton *myButton = (UIButton *)sender;

    [myButton setTitle:@"PRESSED" forState:UIControlStateNormal];
}

-(void)setLetGo:(id)sender
{
    UIButton *myButton = (UIButton *)sender;

    [myButton setTitle:@"LET GO" forState:UIControlStateNormal];
}

Upvotes: 0

Ben
Ben

Reputation: 3485

I would do this with a GestureRecognzier. Here is some code:

- (void)viewDidLoad
{
    [super viewDidLoad];

    UILongPressGestureRecognizer *gr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(buttonIsPressed:)];
    gr.minimumPressDuration = 0.1;
    [self.button addGestureRecognizer:gr];
}

-(IBAction)buttonIsPressed:(UILongPressGestureRecognizer*)gesture {
    if (gesture.state == UIGestureRecognizerStateBegan) {
        self.label.text = @"Button is pressed!";
    }
    else if (gesture.state == UIGestureRecognizerStateEnded) {
        self.label.text = @"Button is not pressed";
    }
}

You need an IBOutlet for the label and the button.

Upvotes: 1

Related Questions