1

我正在使用个人资料注册视图控制器,当用户从 UIPickerController 选择城市时,我想更新我的 UIButton 的标题。用户选择城市后,按钮的标题不会更新。

我尝试使用 DispatchQueue.main.async 并且无法正常工作我试图在关闭我展示城市选择器的视图后更新 didSet。当我运行我的代码时,该值给出了正确的标题,但没有从我的视图中更新和重新加载数据。

第一个视图

 import UIKit
import Firebase

class PersonalInfoController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {

//MARK: Variables
var finalCity: String? {
    didSet {
        guard let userCity = self.finalCity else { return }
        print(cityPicker.currentTitle)
        self.cityPicker.setTitle(userCity, for: .normal)
        print(cityPicker.currentTitle)
    }
}

let cityPicker: UIButton = {
    let button = UIButton(type: .system)
    button.setTitle("City", for: .normal)
    button.backgroundColor = UIColor.rgb(red: 248, green: 101, blue: 46)
    button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 17)
    button.setTitleColor(UIColor.white, for: .normal)
    button.layer.cornerRadius = 20
    button.clipsToBounds = true
    button.addTarget(self, action: #selector(handlePickCity), for: .touchUpInside)
    return button
}()
//MARK: ViewDidLoad
override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = UIColor.rgb(red: 235, green: 235, blue: 228)
    navigationController?.isNavigationBarHidden = true
    setupSubViews()
    stackView()
}
@objc func handlePickCity() {
    let selectVC = UINavigationController(rootViewController: SelectCity())
    selectVC.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
    present(selectVC, animated: true, completion: nil)
}

第二视图(选择器呈现)

import UIKit

class SelectCity: UIViewController {

//MARK: Variables
let cities = ["Chico", "Orland"]
let picker = CityPicker()
var selectedCity: String?

override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = UIColor.black.withAlphaComponent(0.7)

    navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(handleDone))

    picker.delegate = self
    picker.dataSource = self
    view.addSubview(picker)
    picker.anchor(top: nil, left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
}

//MARK: Action Handler
@objc func handleDone(){
    let userInfoVC = PersonalInfoController()
    userInfoVC.finalCity = selectedCity
    self.dismiss(animated: true, completion: nil)
}
}

extension SelectCity: UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
    return 1
}

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

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    return cities[row]
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    selectedCity = cities[row]
}
}

我的控制台在前后打印 currentTitle。这是控制台:

这是用户从选择器中选择城市后的当前 Optional("City")

这是在用户选择城市 Optional("Orland") 之后

4

2 回答 2

1

问题是您的 cityPicker 每次都在创建新的按钮实例。

你可以做

var cityPicker: UIButton = UIButton()

创建一个返回 UIButton 的方法。

func getButton() -> UIButton { 
  let button = UIButton(type: .system)
    button.setTitle("City", for: .normal)
    button.backgroundColor = UIColor.rgb(red: 248, green: 101, blue: 46)
    button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 17)
    button.setTitleColor(UIColor.white, for: .normal)
    button.layer.cornerRadius = 20
    button.clipsToBounds = true
    button.addTarget(self, action: #selector(handlePickCity), for: .touchUpInside)
    return button
}

cityPicker = getButton()

然后你可以设置标题

cityPicker.setTitle(userCity, for: .normal)
于 2018-12-26T07:19:24.670 回答
1

您的问题出在下面的方法中,在该方法中您正在创建新控制器并将selectedCity字符串分配给新实例。这样您现有的PersonalInfoController就不会被更新。

//MARK: Action Handler
@objc func handleDone(){
    let userInfoVC = PersonalInfoController() //New PersonalInfoController is creating and existing controller won't be updated.
    userInfoVC.finalCity = selectedCity
    self.dismiss(animated: true, completion: nil)
}

因此,您可能必须遵循某种Delegate模式在 ViewController 之间发送数据。

例子:

protocol SelectCityDelegate {

    func didSelectCity(_ city:String)
}

class PersonalInfoController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, SelectCityDelegate {

    //////

    @objc func handlePickCity() {

        let selectCityController = SelectCity()
        selectCityController.delegate = self

        let selectVC = UINavigationController(rootViewController: selectCityController)

        selectVC.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
        present(selectVC, animated: true, completion: nil)
    }

    func didSelectCity(_ city: String) {

        finalCity = city
    }

    //////
}

class SelectCity: UIViewController {

    /////

    weak var delegate:SelectCityDelegate?

    //MARK: Action Handler
    @objc func handleDone(){

        delegate?.didSelectCity(selectedCity)

        self.dismiss(animated: true, completion: nil)
    }

    /////
}

但我会建议您在您的内部实现城市选择器视图,PersonalInfoController而不是仅为选择器创建新控制器。

于 2018-12-26T07:28:50.740 回答