Most of the answers here don't answer the specific question of how to set a button color based on selected state which implies another color is desired for unselected state. I struggled with this for quite some time and wanted to share my solution for others to use.
My example uses a UISegmentedControl
with three segments. The unselected color for all three should be the same to give it a uniform look. The selected state for the first and last segment have unique colors.

The issue is that the segmented control is not guaranteed to be in the same order so the colors will get mixed up as you select back and forth. Dan posted a solution that uses tags but unfortunately it's no longer guaranteed to work for iOS 6 and up.
Most of this code is taken from this post. I changed it slightly to have unique selected colors.
What makes it work is the sorting but take note of these 2 important lines for setting the selected color:
NSInteger selectedIdx = betterSegmentedControl.selectedSegmentIndex;
[[sortedViews objectAtIndex:selectedIdx] setTintColor:[self.segmentColors objectAtIndex:selectedIdx]];
- (void) updateSegmentColors
{
UIColor *checkColor = [UIColor colorWithRed: 29/255.0 green:166/255.0 blue:47/255.0 alpha:1.0];
NSArray *segmentColors = [[NSArray alloc] initWithObjects:checkColor, [UIColor blueColor], [UIColor redColor], nil];
UISegmentedControl *betterSegmentedControl = self.StatusControl;
// Get number of segments
NSUInteger numSegments = [betterSegmentedControl.subviews count];
// Reset segment's color (non selected color)
for( int i = 0; i < numSegments; i++ ) {
// reset color
[[betterSegmentedControl.subviews objectAtIndex:i] setTintColor:nil];
[[betterSegmentedControl.subviews objectAtIndex:i] setTintColor:[UIColor blueColor]];
}
// Sort segments from left to right
NSArray *sortedViews = [betterSegmentedControl.subviews sortedArrayUsingFunction:compareViewsByOrigin context:NULL];
// Change color of selected segment
NSInteger selectedIdx = betterSegmentedControl.selectedSegmentIndex;
[[sortedViews objectAtIndex:selectedIdx] setTintColor:[self.segmentColors objectAtIndex:selectedIdx]];
// Remove all original segments from the control
for (id view in betterSegmentedControl.subviews) {
[view removeFromSuperview];
}
// Append sorted and colored segments to the control
for (id view in sortedViews) {
[betterSegmentedControl addSubview:view];
}
}
NSInteger static compareViewsByOrigin(id sp1, id sp2, void *context)
{
// UISegmentedControl segments use UISegment objects (private API). But we can safely cast them to UIView objects.
float v1 = ((UIView *)sp1).frame.origin.x;
float v2 = ((UIView *)sp2).frame.origin.x;
if (v1 < v2)
return NSOrderedAscending;
else if (v1 > v2)
return NSOrderedDescending;
else
return NSOrderedSame;
}
I placed the code in it's own method because I'm loading these segmented controls in a table view and need to run it upon loading (existing states from storage) and when a user changes a selection. Now I just need to call [Self updateSegmentColors];
when something changes.