Take the 2-minute tour ×

In my code I am using a UISegmentedControl as a "button" with only ONE segment and the momentary property set to YES. In versions of the SDK prior to iOS 4, this was not a problem, but it appears that now iOS 4 requires that there be at least 2 segments. The following code throws an exception:

NSArray *titles = [NSArray arrayWithObject:@"Button Title"];
myButton = [[UISegmentedControl alloc] initWithItems:titles];

and now in Interface Builder you cannot even create a UISegmentedControl with less than 2 segments. It logs the following error when building:

"The number of segments property of a segmented control must be greater than or equal to 2."

I'm kinda stumped. Any work arounds for this? I tried to create a UISegmentedControl with two buttons and then remove one programmatically and that "works" as it doesn't cause the app to crash. I get a button in iOS 3 and nothing in iOS 4. Any ideas?

share|improve this question
This is bugging me, too. I'm using it as a replacement for the "glass" button, which Apple has still not put into the public part of the SDK. –  Shaggy Frog Jul 30 '10 at 6:39
I used to do the same for colored buttons in iOS3, but they seem to have removed this functionality in iOS4. –  Vibhor Goyal Aug 20 '10 at 16:41
It looks like you forgot nil as a second element in titles array. See my answer below for working code. –  spbfox Aug 22 '10 at 6:05
arrayWithObject: only takes one argument. You're thinking arrayWithObjects: –  Adolfo Aug 23 '10 at 5:44
Sorry, you are right. But the bottom line is that arrayWithObjects with nil as a second parameter will do the trick. –  spbfox Aug 23 '10 at 16:18

8 Answers 8

up vote 6 down vote accepted

Really strange. It still works fine for me both in iOS4 simulator and device (this is a real working snippet from my code):

NSArray *laterContent = [NSArray arrayWithObjects: @"Maybe later", nil];
UISegmentedControl *later = [[UISegmentedControl alloc] initWithItems:laterContent];
CGRect frame = CGRectMake(  20,
                          self.alert.bounds.size.width/2 - 30,

later.frame = frame;

later.selectedSegmentIndex = -1;

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

later.segmentedControlStyle = UISegmentedControlStyleBar;
later.tintColor = [UIColor colorWithRed:130.0f/255.0f green:74.0f/255.0f blue:54.0f/255.0f alpha:0.8f];
later.momentary = YES;
later.alpha = 0.9;
share|improve this answer
When I press on the single segment button, it does call the selector but it does not show the button being pressed. Do I miss anything? –  Wayne Lo Nov 23 '11 at 7:19

Have you tried this:

[myButton removeAllSegments];
[myButton insertSegmentWithTitle:@"Press this" atIndex:0 animated:NO];
share|improve this answer
Have you tried this? –  Shaggy Frog Aug 10 '10 at 18:15
Yes, I had tried this and it was working for the device but not the simulator. In the simulator I got a blank button (as in not visible at all) but it showed fine on the device and in fact is in a shipping app. –  Adolfo Aug 20 '10 at 21:00
This worked for me. Thanks!! –  Das Sep 15 '12 at 7:27

It's not exactly a code-related solution but: I hit a similar issue and ended up drawing my own similar looking resources in Photoshop. It was not terribly difficult to do and removed a particular bad "code smell", IMO.

share|improve this answer

Well two possibilities:

1) Create a button and the set background image as the single dot of the UISegmentedControl

If your SegmentedControl is a class variable just replace the @property

@property (nonatomic, retain) IBOutlet UIButton *button;

In the viewDidLoad-function add the following

-(void) viewDidLoad
    [super viewDidLoad];
    self.button = [UIButton alloc] init];
    [self.button setBackgroundImage:[UIImage imageNamed:@"segmentedDot.png"] forState:(UIControlState)UIControlStateNormal];

2) Set the amount of segments to three of your UISegmentedControl and afterwards set the width to 20 - now only the dot in the middle will be shown. Dont forget, if the user interacts with the UISegmentedControl, set the currentElement again to the second segment, else the dot will be in light grey instead of white state.

3) Place a button or a small view over the unwanted second dot of the UISegmentedControl in InterfaceBuilder. Make sure the backgroundcolor is even. When you are using a button set the state for "user interaction" in attribute inspector to disabled. As type I would chose "custom" since you won't have some borders in your button ;) Now male again sure, that always the first dot is the active Element.

However I think solution one should be the way you should go, since Apple thought something about it, when they disabled the 1-dot-SegmentedControl. Since you are using the Control as a button the Element you are looking fpr should be a button. ;)

share|improve this answer

There's no workaround in iOS 4. If you need this functionality, file a bug (enhancement request) at bugreport.apple.com.

share|improve this answer
It's strange to think of asking for old functionality to be restored as an enhancement. It's still unclear why this is a problem... –  Shaggy Frog Aug 13 '10 at 23:08

I found if you have a previous project with a single-segment UISegmentedControl, you can open both that project and your new one in Interface Builder and drag (or copy/paste) the single-segment UISegmentedControl to your new view controller. It will work fine in both your app and Interface Builder, just don't change the number of segments from 1 to anything else as it won't let you go back. I'm using Xcode 4.6.2 and iOS 6.

share|improve this answer

The editor in Interface Builder won't let you change the number of segments to be less than 1, but you can make a segmented control in IB by editing the .xib xml manually.

  1. Right click on the .xib containing the segmented control
  2. Choose Open As -> Source Code from the popup menu.
  3. Find "<segments> which is the beginning of the xml array of segments. The whole thing should look like:

        <segment title="Segment 1 Title"/>
        <segment title="Segment 2 Title"/>
  4. Just delete <segment title="Segment 2 Title"/> so there is only one segment element.

  5. Right click the .xib again and choose Open As -> Interface Builder - iOS to go back to interface builder.

You should also probably set the segmented control to "momentary" mode.

I don't get any errors compiling or running this. Of course, this is a hack, and may break things in some circumstances or in a future iOS release.

share|improve this answer

You can also use removeSegmentAtIndex:animated:. If you create a segmented control in a storyboard or xib with two segments, you can remove one like this:

[self.sortButton removeSegmentAtIndex:1 animated:NO];
share|improve this answer

Your Answer


