如何使用 didSet 更新 UIButton 的 .setTitle?
Posted
技术标签:
【中文标题】如何使用 didSet 更新 UIButton 的 .setTitle?【英文标题】:How to update .setTitle for a UIButton using didSet? 【发布时间】:2018-12-26 07:08:47 【问题描述】:我正在使用个人资料注册视图控制器,当用户从 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。 这是控制台:
这是用户从picker中选择城市后的当前 可选(“城市”)
这个是用户选择城市后的 Optional("Orland")
【问题讨论】:
【参考方案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
中实现 City Picker 视图,而不是仅为选择器创建新控制器。
【讨论】:
谢谢。我想在同一个视图中输入我的代码,但我不知道我在想什么。投票回答和推荐【参考方案2】:问题是您的 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)
【讨论】:
以上是关于如何使用 didSet 更新 UIButton 的 .setTitle?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 `Codable` 协议调用`didSet` 方法
将CABasicAnimation添加到子类UIButton - 如果已启用
已发布值上的 SwiftUI toggle() 函数停止使用 Swift 5.2 触发 didSet