UISegmentedControl.noSegment stopped working with Xcode 11, iOS 13 [duplicate]

大兔子大兔子 提交于 2019-12-07 15:41:12

问题


I've had two segmented controls stacked on top of each other, each with two options, so there's a 2x2 grid of filtering options for a search field. This has worked fine, but I just updated to Xcode 11 and UISegmentedControl.noSegment has stopped working when I try to update it in response to user selection. However, it works when I set the initial value to .noSegment in the property observer. isMomentary is set to false. The outlets are all set up correctly. Is there some update to UISegmentedControl behavior I'm missing, or is this a bug?

New, incorrect behavior shown here.

Current code that was working before, and stopped working after update:

@IBOutlet private weak var segmentedControlOne: UISegmentedControl!

@IBOutlet private weak var segmentedControlTwo: UISegmentedControl! {
    didSet {
        // Start with no segment selected on this control. This works!
        segmentedControlTwo.selectedSegmentIndex = -1
    }
}

@IBAction private func oneIndexChanged(_ sender: UISegmentedControl) {
    //Turn off selection on second control while first is selected
    segmentedControlTwo.selectedSegmentIndex = UISegmentedControl.noSegment

    let i = sender.selectedSegmentIndex
    if i == 0 {
        searchType = .users
    } else {
        searchType = .contributors
    }
}

@IBAction private func twoIndexChanged(_ sender: UISegmentedControl) {
    //Turn off selection on first control while second is selected
    segmentedControlOne.selectedSegmentIndex = UISegmentedControl.noSegment

    let i = sender.selectedSegmentIndex
    if i == 0 {
        searchType = .articles
    } else {
        searchType = .categories
    }
}

回答1:


Thanks for asking this question. I ran into the same issue, so was great to get some confirmation it wasn't just something I was missing.

While Apple hopefully fixes this bug soon, I implemented the following workaround by recreating the segments. This code sample is based on a UISegmentedControl with images as segments, you could of course implement the same approach for title strings:

public func resetSegmentedControl(_ control: UISegmentedControl) {
    if #available(iOS 13, *) {
        // workaround: recreate the segments
        let numSegments = control.numberOfSegments
        let segmentImages = (0..<numSegments).compactMap { control.imageForSegment(at: $0) }
        control.removeAllSegments()
        for (index, image) in segmentImages.enumerated() {
            control.insertSegment(with: image, at: index, animated: false)
        }
    } else {
        // for earlier versions of iOS, just reset the selectedSegmentIndex
        control.selectedSegmentIndex = UISegmentedControl.noSegment
    }
}

There's a slight flicker when removing and re-inserting the segments, but for me that's preferable to the broken state.

EDIT

As pointed out by @matt in the comment below, all that's needed is a call to setNeedsLayout,i.e.:

control.selectSegmentIndex = .noSegment
control.setNeedsLayout()


来源:https://stackoverflow.com/questions/58067441/uisegmentedcontrol-nosegment-stopped-working-with-xcode-11-ios-13

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!