如何使用didSet为UIButton更新.setTitle?

时间:2018-12-26 07:08:48

标签: swift uibutton uipickerview didset

我正在使用配置文件注册视图控制器,当用户从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(“ Orland”)

之后

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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内实施“城市选择器”视图,而不是仅为选择器创建新的控制器。