Search code examples
arraysswiftuisegmentedcontrol

ObjectAtIndex index 0 beyond bounds for empty array in segmented Control


hi I want to make segmented control programmatically, but it error when running simulator "ObjectAtIndex index 0 beyond bounds for empty array". I try to find the problem but can't find it. this is my code

    let segmentedControl    = GSegmentedControl(frame: .zero)
    let segmentedIndicator  = UIView()

    segmentedControl.setTitle("Daily", forSegmentAt: 0)
    segmentedControl.setTitle("Subject", forSegmentAt: 1)
    view.addSubview(segmentedControl)
    segmentedControl.addTarget(self, action: #selector(ViewController.indexChange(in:)), for: .valueChanged)

    @objc func indexChange(in segmented: UISegmentedControl) {
        let numberOfSegmented   = CGFloat(segmentedControl.numberOfSegments)
        let selectIndex         = CGFloat(segmented.selectedSegmentIndex)
        let titleCount          = CGFloat(segmentedControl.titleForSegment(at: segmented.selectedSegmentIndex)!.count)

        view.addSubview(segmentedIndicator)
        segmentedIndicator.backgroundColor = .systemPink
        segmentedIndicator.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            segmentedIndicator.topAnchor.constraint(equalTo: segmentedControl.bottomAnchor, constant: 3),
            segmentedIndicator.heightAnchor.constraint(equalToConstant: 2),
            segmentedIndicator.widthAnchor.constraint(equalToConstant: CGFloat(15 + titleCount * 8)),
            segmentedIndicator.centerXAnchor.constraint(equalToSystemSpacingAfter: segmentedControl.centerXAnchor, multiplier: CGFloat(numberOfSegmented / CGFloat(3) + CGFloat(selectIndex-1.0) * 2.0))

        ])

        UIView.animate(withDuration: 0.5, animations: {
            self.view.layoutIfNeeded()
            self.segmentedIndicator.transform = CGAffineTransform(scaleX: 1.4, y: 1)
        }) { finish in
            UIView.animate(withDuration: 0.4) {
                self.segmentedIndicator.transform = .identity
            }
        }
    }

Solution

  • Between

    let segmentedControl = GSegmentedControl(frame: .zero)
    

    and

    segmentedControl.setTitle("Daily", forSegmentAt: 0)
    segmentedControl.setTitle("Subject", forSegmentAt: 1)
    

    you didn’t set numberOfItems, so you have a count of 0, but try to access first (and second) index.

    To fix this, eather change init:

    let segmentedControl = GSegmentedControl(items: ["Daily", "Subject"])
    

    and remove the setTitle.. lines
    or change the setTitle lines to

    segmentedControl.insertSegment(withTitle: "Daily", at: 0, animated: false)
    segmentedControl.insertSegment(withTitle: "Subject", at: 1, animated: false)