UIPickerView зависает при перезагрузке UI - PullRequest
1 голос
/ 28 мая 2020

Пользовательский интерфейс моего приложения зависает, когда индекс UIPickerView достигает 1 или количество элементов равно 2. Я действительно запутался, потому что это работало, а затем внезапно сломалось. Я провел небольшое исследование и обнаружил, что это может быть связано с веткой. Может ли кто-нибудь помочь мне решить проблему с UIPickerView?

// class implements UIPickerViewDelegate, UIPickerViewDataSource, UIGestureRecognizerDelegate

     @IBOutlet weak var planetPickerView: UIView!
     var planetPicker: UIPickerView!

Просмотр загружен:

override func viewDidLoad() {
     super.viewDidLoad()
     //Other code not important 
     configurePlanetPicker()
}

Реализация UIPickerView: (skyBalls - это массив классов с различными данными в качестве получателей)

 func configurePlanetPicker() {
        planetPicker = UIPickerView(frame: CGRect(x: 0, y: 0, width: planetPickerView.frame.width, height: 70))
        planetPicker.delegate = self
        planetPicker.dataSource = self
        planetPicker.transform = CGAffineTransform(rotationAngle: CGFloat(-90 * (Double.pi/180)))
        planetPicker.frame = CGRect(x: -100, y: 0, width: planetPickerView.frame.width + 200, height: 70)
        planetPicker.showsSelectionIndicator = false
        planetPickerView.backgroundColor = .clear
        let tap = UITapGestureRecognizer(target: self, action: #selector(pickerTapped))
        tap.delegate = self
        planetPicker.addGestureRecognizer(tap)
        planetPickerView.addSubview(planetPicker)
    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int { return 1 }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {return skyBalls.count }

    func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat { return 70 }

    func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat { return 70 }

    func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
        let mainView = UIView(frame: CGRect(x: 0, y: 0, width: 70, height: 70))

        let image = UIImageView(frame: CGRect(x: 15, y: 10, width: 40, height: 40))
        image.image = UIImage(named: "\(skyBalls[row].getImage().split(separator: ".")[0])")
        image.contentMode = .scaleAspectFit
        mainView.addSubview(image)

        let titleLbl = UILabel(frame: CGRect(x: 0, y: 50, width: 70, height: 20))
        titleLbl.text = skyBalls[row].getName()
        titleLbl.textColor = .white
        titleLbl.textAlignment = .center
        titleLbl.adjustsFontSizeToFitWidth = true
        mainView.addSubview(titleLbl)

        mainView.transform = CGAffineTransform(rotationAngle: 90 * CGFloat((Double.pi/180)))
        return mainView
    }

    @objc func pickerTapped(tapRecognizer: UITapGestureRecognizer) {
        if tapRecognizer.state == .ended {
            let rowHeight = planetPicker.rowSize(forComponent: 0).height
            let selectedRowFrame = planetPicker.bounds.insetBy(dx: 0, dy: (planetPicker.frame.height - rowHeight) / 2)
            let userTappedOnSelectedRow = selectedRowFrame.contains(tapRecognizer.location(in: planetPicker))
            if userTappedOnSelectedRow {
                let selectedRow = planetPicker.selectedRow(inComponent: 0)
                upgradePlanetName = skyBalls[selectedRow].getName()
                let settings = UIStoryboard(name: "PlanetUpgrade", bundle: .main).instantiateViewController(withIdentifier: "Upgrade") as! UpgradeViewController
                self.present(settings, animated: false)
            }
        }
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }

Я перезагружаю UIPickerView при нажатии кнопки, которая увеличивает размер массива skyBalls:

planetPicker.reloadAllComponents()

НО проблема все еще возникает, если planetPicker.reloadAllComponents() полностью удален во всех формах из проекта.

Я попытался перезапустить свои ma c, iphone и xcode, а также удалить производные данные. Я очистил папку сборки, и, похоже, ничего не решило проблему.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 28 мая 2020

Итак, я обнаружил, что это вообще не вина UIpickerView. Итак, осмотревшись, я попробовал следующее:

1) Откройте «Навигатор точек останова»

2) нажмите кнопку «+» и выберите параметр «Exception Breakpoint»

затем я перешел к root проблемной ведьме, которая была индексом массива за пределами, который по какой-то причине не приводил к сбою приложения.

0 голосов
/ 28 мая 2020

, когда вам нужно обновить свое представление, вы должны всегда вызывать .reloadAllComponents() в основном потоке. DispatchQueue.main.async должно решить проблему.

DispatchQueue.main.async {
    self.planetPickerView.reloadAllComponents()
}
...