快速从 UIPickerView 的选定行设置 UIButton 的标题

Posted

技术标签:

【中文标题】快速从 UIPickerView 的选定行设置 UIButton 的标题【英文标题】:Set Title of UIButton from Selected Row of UIPickerView in swift 【发布时间】:2019-02-28 08:33:36 【问题描述】:

我正在尝试从 uipickerview 的选定行中设置我的按钮标题。但是,我似乎找不到有效的解决方案。

我已将变量设置为全局变量,因此我可以访问选定变量。但是,我似乎无法准确指出用户何时单击退出按钮并能够更新我的按钮标题。

我尝试过的事情:

全局函数(无法工作,因为您无法指定要更改名称的按钮) Dispatchqueue.main.async - 没有更新我的标题。这里的想法是让它不断检查字符串的变化。

我在这里找到的解决方案是在 Obj-C 中。我尝试将其转换为 swift https://objectivec2swift.com/#/converter/code/,但没有成功。 Set Title of UIButton from Selected Row of UIPickerView

@IBAction func CountryPickButton(_ sender: UIButton) 

        Global.setPickerDataSource(data:["Test","test2","test3"])
        Global.setPickerCompletionHandler(int:0)
        let popOverVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PickerViewPopUpId") as! PickerViewController
        //CountryPickButtonDetector = sender as? UIButton
        self.addChild(popOverVC)
        popOverVC.view.frame = self.view.frame
        self.view.addSubview(popOverVC.view)
        popOverVC.didMove(toParent: self)
        popOverVC.callback  value in
        //CountryPickButton.title.text = value
        sender.setTitle(value, for: UIControl.State)
    
    

import UIKit
var test = ""

class PickerViewController: UIViewController 
    @IBOutlet weak var PickerView: UIPickerView!
    var callback : ((String) -> Void)?
    override func viewDidLoad() 
        super.viewDidLoad()
        //self.view.backgroundColor = UIColor.black.withAlphaComponent(0.8)
        PickerView.dataSource = self
        PickerView.delegate = self
        // Do any additional setup after loading the view.
    
    @IBAction func ExitButton(_ sender: Any) 
        switch Global.pickerCompletionHandler 

        case 0:
            callback?(Global.pickerResult ?? "")
            Global.setProfileCountry(string:
                Global.pickerResult ?? "")
        default:
            print("nothing")

        
        self.view.removeFromSuperview()
    



extension PickerViewController: UIPickerViewDelegate, UIPickerViewDataSource 
    func numberOfComponents(in pickerView: UIPickerView) -> Int 
        return 1 // can be more than 1 component like time/date/year
    

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int 
        return Global.pickerDataSource?.count ?? 1
    

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) 
        //Global.pickerResult = Global.pickerDataSource?[row]
        Global.setPickerResult(result: Global.pickerDataSource?[row] ?? "Test" )
    

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? 
        return Global.pickerDataSource?[row]
    




全局

import Foundation

struct Global 
    static var pickerDataSource:[String]? = nil
    static var pickerResult:String? = nil
    static var pickerCompletionHandler:Int? = 0
    static var profileCountry:String? = nil

    static func setPickerDataSource(data:[String]) 
        Global.pickerDataSource = data
    
    static func setPickerResult(result:String) 
        Global.pickerResult = result
    
    static func setPickerCompletionHandler(int: Int) 
        Global.pickerCompletionHandler = int
    
    static func setProfileCountry(string: String)
    
        Global.profileCountry = string
    

【问题讨论】:

不要检查。得到通知!实现选择器视图委托方法didSelectRow 并通知(使用回调闭包、协议/委托或Notification)有关更改。 我的 didselectrow 看起来像这样 func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) //Global.pickerResult = Global.pickerDataSource?[row] Global.setPickerResult(result : Global.pickerDataSource?[row] ?? "Test" ) 我应该如何更改它以通知我? @vadian 在 IBAction 中有对按钮的引用。添加在didSelectRow 中调用的回调闭包。在闭包的主体中设置标题 @vadian 我不会撒谎,我对此很陌生。如何连接回调闭包和 didselectrow,我从来没有做过回调闭包。这是在选择器视图控制器还是带有按钮的视图控制器上编码的。 遗憾的是,问题中的代码过于模糊,无法提供具体建议。 【参考方案1】:

我不知道Global 的全部内容是什么,最简单的解决方案可能是扩展pickerCompletionHandler,但这是另一个(简单)的解决方案:

PickerViewController 中添加一个回调,传递一个String 值并且没有返回值

var callback : ((String) -> Void)?

并在exitButton 中调用它(请变量名和函数名应该以小写字母开头)

@IBAction func exitButton(_ sender: Any) 
    switch Global.pickerCompletionHandler 

    case 0:
        callback?(Global.pickerResult ?? "")
        Global.setProfileCountry(string:
            Global.pickerResult ?? "")
    default:
        print("nothing")

    
    self.view.removeFromSuperview()

countryPickButton(同样:小写字母)中设置回调并将sender设置为真实类型。回调设置标题

@IBAction func countryPickButton(_ sender: UIButton) 

    Global.setPickerDataSource(data:["Test","test2","test3"])
    Global.setPickerCompletionHandler(int:0)
    let popOverVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PickerViewPopUpId") as! PickerViewController
    popOverVC.callback =  value in 
        sender.setTitle(value, for: .normal)
    
...

【讨论】:

这让我“无法调用非函数类型的值 ((String) -> Void)?”。我确实添加了 var 回调:((String) -> Void)?到pickerViewController,为了清楚起见,我会添加我的Globals,主要是为了让我可以通过多个swift文件交流信息 我认为这是在说回调不是一个函数,因此不能返回一个值......所以做错了什么吗?我已经编辑了代码以将您添加的内容放入 请仔细阅读我的代码。将 IBAction 的 sender 类型更改为 UIButton 并使用 sender.title。当函数以大写字母开头时,这正是混乱。实际上,如果 Global 结构仅在 PickerViewController 中使用,它是毫无意义的。 我将 sender 更改为 UIButton,存在相同的错误,首先,“无法分配给属性:'title' 是一种方法”,然后我将其更改为:“popOverVC.callback value in sender.setTitle (value, for: UIControl.State) " "Cannot call value of non-function type '((String) -> Void)?'" 我又更新了代码 这实际上是一个可重复使用的pickerviewcontroller,可以根据使用它的屏幕来更改要选择的数据。因此我不得不将它设置为一个全局变量。我将来也会合并登录和注册令牌

以上是关于快速从 UIPickerView 的选定行设置 UIButton 的标题的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中为选定的 UIPickerView 行设置动画背景颜色

如何使用 UIPickerView 的选定值作为通知的时间间隔?

显示带有选定行的 UIPickerView

UIPickerView从中间的选定行开始

获取 UIPickerView 中每个组件的选定行

如何从UIPickerView获取选定的值