65

I have added a UISegmentedControl in my application. None of the buttons are selected in normal state. I want to implement a button click event when the first segment is selected, and another event when another button is clicked.

jscs
  • 62,161
  • 12
  • 145
  • 186
Warrior
  • 37,935
  • 44
  • 133
  • 211

8 Answers8

132

If I understand your question correctly, you simply have to implement a target-action method (supported by UIControl which is UISegmentedControl's parent class) for the constant UIControlEventValueChanged, exactly like in the example given in UISegmentControl's reference documentation.

i.e.

[segmentedControl addTarget:self
                     action:@selector(action:)
           forControlEvents:UIControlEventValueChanged];

used for a message with the following signature:

- (void)action:(id)sender

or

[segmentedControl addTarget:self
                     action:@selector(action:forEvent:)
           forControlEvents:UIControlEventValueChanged];

for

- (void)action:(id)sender forEvent:(UIEvent *)event

or

[segmentedControl addTarget:self
                     action:@selector(action)
           forControlEvents:UIControlEventValueChanged];

for the simplest method:

- (void)action

which are standard types of target-action selectors used in UIKit.

Xeaza
  • 1,116
  • 1
  • 15
  • 19
macbirdie
  • 15,585
  • 6
  • 44
  • 52
  • 5
    Just a quick heads up: I believe if you define the method as -(void)action then you'll want the selector to be @selector(action) or else it will crash. – Philippe Sabourin Jan 10 '12 at 15:24
  • 1
    The selector must match the message exactly, but without parameters, so @selector(action:forEvent:) is the selector for "- (void)action:(id)sender forEvent:(UIEvent *)event" – Jonathan Oct 09 '12 at 10:27
  • I have a question, will this action be called even if I change the selected index manually? If I don't want that to happen can I listen to some other control event? – JohnVanDijk Jan 05 '16 at 09:41
  • Surely you've figured it out by now, but no, the target is not notified on changes applied using code. Only through user's action. – macbirdie Nov 19 '17 at 19:09
69

try this:

- (IBAction)segmentSwitch:(UISegmentedControl *)sender {
      NSInteger selectedSegment = sender.selectedSegmentIndex;

      if (selectedSegment == 0) {

      }
      else{

      }
    }
Berik
  • 7,306
  • 2
  • 26
  • 38
Nuno Ferro
  • 1,183
  • 11
  • 15
11

Simple version in swift updated

func loadControl(){
     self.yourSegmentedControl.addTarget(self, action: #selector(segmentSelected(sender:)), forControlEvents: .valueChanged)
}

func segmentSelected(sender: UISegmentedControl)
{
    let index = sender.selectedSegmentIndex

    // Do what you want
}
Beninho85
  • 2,977
  • 23
  • 21
  • 3
    latest swift syntax: self.segmentedControl.addTarget(self, action: #selector(segmentSelected(sender:)), for: .valueChanged) – Gilles May 04 '17 at 07:16
9

Try this one,

    UISegmentedControl  * travelModeSegment = [[UISegmentedControl alloc] initWithItems:
    [NSArray arrayWithObjects:NSLocalizedString(@"Driving", nil),                 NSLocalizedString(@"Walking", nil), nil]];
    [travelModeSegment setFrame:CGRectMake(9.0f, 0.0f, 302.0f, 45.0f)];
    [cell addSubview:travelModeSegment];
    [travelModeSegment release];

then write an action,

     if (travelModeSegment.selectedSegmentIndex == 0) {
        //write here your action when first item selected
    } else {
        //write here your action when second item selected
    }

I hope it will help you

Sivanathan
  • 1,205
  • 3
  • 13
  • 25
7

It's worth noting that the selector has to match a method exactly, but without the actual parameters.

@selector(action)
    => -(void) action { ..code.. }

@selector(action:) 
    => -(void) action:(id)sender { ..code.. }

@selector(action:forEvent:) 
    => -(void) action:(id)sender forEvent:(UIEvent *)event { ..code.. }

This confused me for the longest time, and it's not quite clear from the earlier answers.

Jonathan
  • 23,467
  • 12
  • 62
  • 81
  • 1
    Thank you very much for the effort in making your explanation, Jonathan. This has been one of those things I've needed to clarify for myself for ... erm ... 'quite sometime now' ;-) 'Nicely presented, too; it's gone straight in my code library! :-) – Slowburner Jul 21 '13 at 06:50
6

for SWIFT use this:

segmentedControl.addTarget( self, action: "segmentSelected:", forControlEvents: UIControlEvents.ValueChanged )

and implement a method like this:

func segmentSelected(sender: UISegmentedControl)
{
    println("selected index: \(sender.selectedSegmentIndex)")
}

Extend UISegmentedControl if you want to call a specific action when the selected segment is selected:

class CustomSegmentedControl : UISegmentedControl
{        
    override init()
    {
        super.init()
    }

    override init(frame:CGRect)
    {
        super.init(frame:frame)
    }

    required init(coder aDecoder: NSCoder) {
       super.init(coder: aDecoder)
    }

    func valueChanged(index:Int)
    {
         // ACTION GOES HERE
    }      
}

and call your "valueChanged" in "segmentSelected" like this:

func segmentSelected(sender: CustomSegmentedControl)
{
    println("selected index: \(sender.selectedSegmentIndex)")
    sender.valueChanged(sender.selectedSegmentIndex)
}
dy_
  • 2,205
  • 21
  • 26
4

Simple like that, you need to make the action using the storyboard to the view controller in order to make this action to work.

- (IBAction)searchSegmentedControl:(UISegmentedControl *)sender
{
    switch (sender.selectedSegmentIndex) {
        case 0:
            NSLog(@"First was selected");
            break;
        case 1:
            NSLog(@"Second was selected");
            break;
        case 2:
            NSLog(@"Third was selected");
            break;
        default:
            break;
    }
}
rafaeljuzo
  • 379
  • 2
  • 8
2

You can attach a handler in IB to the value changed event: UIControlEventValueChanged

or you can do it in code:

[segmentedControl addTarget:self
                     action:@selector(action:)
           forControlEvents:UIControlEventValueChanged];
progrmr
  • 71,681
  • 16
  • 107
  • 147