7

I am the maintainer of STAControls which subclasses various UIControls, one of which is UISegmentedControl. Within that project's sample app, I have the following code (can be downloaded from the aforementioned link):

- (void)textFieldDidEndEditing:(UITextField *)textField {
    NSInteger integer = [textField.text integerValue];
    if (integer < 0 || integer >= self.segmentedControl.numberOfSegments) { this doesn't work
        self.segmentedControl.selectedSegmentIndex = UISegmentedControlNoSegment;
    } else { // this works
        self.segmentedControl.selectedSegmentIndex = integer;
    }
}

In iOS 13 the UISegmentedControlNoSegment assignment is not respected:

enter image description here

While in iOS 12 and prior versions of iOS this performs just fine:

enter image description here

Any idea(s) on how to work around this?

Stunner
  • 12,025
  • 12
  • 86
  • 145
  • I'm having the same problem. Did you submit a bug report to Apple? I'd rather not have to implement your workaround since I don't subclass UISegmentedControl. – deltacrux Sep 27 '19 at 07:22
  • 1
    I did but it's helpful for others to report it as well as it gives them an idea of how big/urgent the problem is. There is no getting around that if you want segmented control to behave this way for iOS 13.0 (and maybe 13.1) you'll need this workaround as when they patch it, it will be released in a new version of iOS. You can use [my subclass of `UISegmentedControl`](https://github.com/Stunner/STAControls/tree/master/STAControls/STAControls/SegmentedControl) instead of rolling your own. See [my answer](https://stackoverflow.com/a/57915487/347339) for how its implemented. – Stunner Sep 28 '19 at 08:57
  • Thanks! I've just reported it as well. Hopefully they'll fix it soon... – deltacrux Sep 29 '19 at 06:05

3 Answers3

12

The solutions given in the other answers are overblown. There is a much simpler workaround: just call setNeedsLayout on the segmented control.

self.seg.selectedSegmentIndex = UISegmentedControl.noSegment
self.seg.setNeedsLayout()
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • This should be the accepted answer. I simply had added coinSelection.setNeedsLayout() and my exiting implementation worked – Mitchell D Oct 05 '19 at 01:51
1

Remove the segment, then create it again. Here's a version in Swift, which only works if you've got text segments (not images). It assumes you've got an Storyboard with a segmented control and a button.

class ViewController: UIViewController {
    @IBOutlet weak var segmentedControl: UISegmentedControl!

    @IBAction func clearSegmentedControl(_ sender: Any) {
        guard segmentedControl.selectedSegmentIndex >= 0 else {
            return
        }

        let index = self.segmentedControl.selectedSegmentIndex
        let title = self.segmentedControl.titleForSegment(at: index) ?? ""

        self.segmentedControl.removeSegment(at: self.segmentedControl.selectedSegmentIndex, animated: false)
        self.segmentedControl.insertSegment(withTitle: title, at: index, animated: false)
        self.segmentedControl.selectedSegmentIndex = UISegmentedControl.noSegment
    }
}

In the Simulator, I couldn't see any flickering. After removing such a selected segment, selectedSegmentIndex becomes -2. This is a bit weird so that's why I added the last line of code, which sets it to the noSegment constant.

Bart van Kuik
  • 4,704
  • 1
  • 33
  • 57
1

Resolved and added a work around in STASegmentedControl. I did the following:

- (void)setSelectedSegmentIndex:(NSInteger)selectedSegmentIndex {
    if (@available(iOS 13.0, *)) {
        if (selectedSegmentIndex == UISegmentedControlNoSegment && self.selectedSegmentIndex >= 0
            && !self.handlingNoSegment)
        {
            self.handlingNoSegment = YES;
            NSUInteger index = self.selectedSegmentIndex;
            NSString *title = [self titleForSegmentAtIndex:self.selectedSegmentIndex];
            [self removeSegmentAtIndex:self.selectedSegmentIndex animated:NO];
            [self insertSegmentWithTitle:title atIndex:index animated:NO];
        }
        self.handlingNoSegment = NO;
    }
    [super setSelectedSegmentIndex:selectedSegmentIndex];
}

Consult this link for the entire commit.

Stunner
  • 12,025
  • 12
  • 86
  • 145