UIPickerView 最佳实践?

Posted

技术标签:

【中文标题】UIPickerView 最佳实践?【英文标题】:UIPickerView best practice? 【发布时间】:2015-02-20 13:34:38 【问题描述】:

一个简短的问题:在注册过程中,我想请用户从值列表中选择一个值。

使用视图控制器添加所有文本字段和选择器视图的值是否正确?由于选择器视图在文本字段区域之间需要如此多的空间,我想知道这种情况下的最佳做法是什么?

这是我目前的代码:

class RegisterViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource

@IBOutlet weak var gradeTextField: UITextField!
@IBOutlet weak var gradePicker: UIPickerView!

let gradePickerValues = ["5. Klasse", "6. Klasse", "7. Klasse"]

func numberOfComponentsInPickerView(pickerView: UIPickerView!) -> Int
    return 1

func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
    return gradePickerValues.count

func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! 
    return gradePickerValues[row]

func pickerView(pickerView: UIPickerView!, didSelectRow row: Int, inComponent component: Int)
    gradeTextField.text = gradePickerValues[row]
    self.view.endEditing(true)


override func viewDidLoad() 
    super.viewDidLoad()

    statusMessageLabel.hidden = true

    gradePicker.dataSource = self
    gradePicker.delegate = self
    gradePicker.hidden = true

    gradeTextField.inputView = UIPickerView()
    gradeTextField.text = gradePickerValues[0]


pickerview 在开始时是隐藏的,只有在我选择文本字段时才会出现,到目前为止还不错...但是 picker view 是空的...

【问题讨论】:

【参考方案1】:

这取决于控制器的外观。如果每个屏幕只有一个选择操作,最好将Table View 放在上面,所选行将是当前选择。

如果屏幕有多个字段,该用户应该使用,那么,在我看来,最好将label + button 放在它上面,当用户按下这个button 时,你只会从屏幕上显示Picker View底部。当用户选择Picker View 中的任何行时,您会更改标签文本,但不要隐藏选择器本身,应通过按上面的“完成”button 来完成。

希望这会有所帮助。


更新

您的问题是因为您忘记设置UIPickerViewdataSource 属性

只要做:gradePicker.dataSource = self in viewDidLoad()

别忘了在这里实现协议:class RegisterViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource


更新 2

终于成功了。如果您在 textFiled 的 inputView 中添加 UIPickerView,那么它不应该在 IB 中。因此,您可以将其从情节提要(或 .xib,如果您使用它)中删除。

然后把代码改成这样:

class RegisterViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource 

    @IBOutlet weak var gradeTextField: UITextField!
    var gradePicker: UIPickerView!

    let gradePickerValues = ["5. Klasse", "6. Klasse", "7. Klasse"]

    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int
        return 1
    

    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
        return gradePickerValues.count
    

    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! 
        return gradePickerValues[row]
    

    func pickerView(pickerView: UIPickerView!, didSelectRow row: Int, inComponent component: Int)
        gradeTextField.text = gradePickerValues[row]
        self.view.endEditing(true)
    

    override func viewDidLoad() 
        super.viewDidLoad()

        gradePicker = UIPickerView()

        gradePicker.dataSource = self
        gradePicker.delegate = self

        gradeTextField.inputView = gradePicker
        gradeTextField.text = gradePickerValues[0]
    

【讨论】:

我刚刚注意到,我的代码中有一个错误,因为选择器视图总是显示在字段之间...现在它从屏幕按钮打开,但我仍然有错误它是空的...我将使用代码详细信息更新我的初始帖子。 是的,这将帮助我理解问题。 哇,你真快!!添加 UIPickerViewDataSource 时,我仍然收到错误“RegisterViewController 不符合协议 UIPickerDataSource” 正如我在最后提到的,不要忘记在类声明中实现这个协议。请比较你的第一行和我的最后一行。 我更新了我的代码!当我删除 !从前 2 个函数开始,不再显示错误。我现在可以运行应用程序,但选择器视图仍然是空的 :-(【参考方案2】:

第一组委托

UIPickerViewDataSource,UIPickerViewDelegate

为 UIPickerView 设置 IBOutlet

@IBOutlet weak var pickerView: UIPickerView!

为数据取一个数组

var arrayFruits = [String]()

在 viewDidLoad() 上写这段代码

  arrayFruits = ["Apple","Banana","Orange","Grapes","Watermelon"]
  self.pickerView.dataSource = self
  self.pickerView.delegate = self

编写选择器视图委托方法:

 //MARK: - Pickerview method
func numberOfComponents(in pickerView: UIPickerView) -> Int 
    return 1

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

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

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) 
    self.labelFruit.text = arrayFruits[row]

100% 工作和测试

【讨论】:

不错的答案,但我发现它适用于“pickerView.delegate = self”。你有 self.pickerView.* 的任何原因?谢谢 我不明白你的意思。 pickerView.delegate = self 用于为 pickerview 设置委托,因此之后所有委托方法都将调用。您也可以使用情节提要进行设置。 是不是 viewDidLoad 太早以至于 self 可用? 为了让它工作,我在 UIPickerView 的出口后添加了@IBOutlet weak var labelFruit: UILabel!,在arrayFruits 初始化后添加了labelFruit.text = arrayFruits[0]

以上是关于UIPickerView 最佳实践?的主要内容,如果未能解决你的问题,请参考以下文章

UIPickerView的使用

点击 uipickerview 时键盘不退出

如何使用 Swift 3 UIPickerView 引用多行?

UIPickerView 在重新加载时冻结 UI

在 iPhone 上水平滚动的 UIPickerView?

超过 1 个 UIPickerView Swift