【问题标题】:UIPickerView - 1st row selection does not call didSelectRowUIPickerView - 第一行选择不调用 didSelectRow
【发布时间】:2009-04-25 06:29:10
【问题描述】:

我的UIView 上有一个UIPickerView 和一个UITextField。我让用户从选择器中选择一个值或在文本字段中输入一个自定义值。

当用户从选择器中选择任何选项时,变量值会被很好地更改(在pickerView:didSelectRow:inComponent: 中)方法。但是如果用户没有在选择器上选择任何值(因为他们想选择已经选择的第一个选项),则不会调用此方法并且选择不会反映在变量中。

我尝试将变量的默认值设置为选择器中的第一个选项。但在这种情况下,当用户编辑文本字段时,变量将具有文本字段的文本。现在如果用户决定再次选择第一个值,新值不会反映在变量中。

我该如何克服这个问题?谢谢。

这是相关代码

在我的viewDidLoad 中,我有此语句将selectText 默认设置为选择器的第一个选项

[self setSelectText:[myArray objectAtIndex:0]];

textFieldShouldReturn

- (BOOL)textFieldShouldReturn:(UITextField *)txtField{
    [txtField resignFirstResponder];
    [self setSelectText:txtField.text];
    return YES;
}

PickerViewDelegate 的 didSelectRow

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    // report the selection to the UI label
    [self setSelectText:[myArray objectAtIndex:[pickerView selectedRowInComponent:0]]];
}

当用户编辑文本然后决定他毕竟要使用选择器的第一个值时,就会出现问题。在这种情况下,他们将关闭键盘并单击选择器的第一个选项(已被选中)。此操作不会调用didSelectRow,因此 selectText 的值不会改变。

为了让用户能够更改selectText 的值,他们首先必须从选择器中选择其他值,然后选择第一行。

【问题讨论】:

  • 如果可以,请发布一些与此问题相关的代码。这将有助于排除故障。

标签: iphone uitextfield uipickerview


【解决方案1】:

每次使用此代码进行选择时,而不是“推送”选择器的值:

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component

当用户单击按钮(或您正在使用的其他事件)时,您应该使用类似于以下内容的“拉动”:

- (void)myAction:(id)sender
{

    NSInteger row = [myPicker selectedRowInComponent:0];
    selectedText = [myArray objectAtIndex:(NSUInteger)row];


}

清除文本:UITextField 类提供了一个用于清除当前文本的内置按钮。因此,如果用户不想要该文本,他可以丢弃它。

myTextField.clearButtonMode = UITextFieldViewModeAlways; 

所以在脚本中,您会检查TextField 是否有值,如果确实有值,则使用TextField,如果没有值,则从Picker 中提取信息。

【讨论】:

  • 谢谢。但这里的问题是用户可以选择在文本字段中指定自定义值。因此,用户有可能输入一些文本。现在,如果我按照您的建议进行操作,用户输入的任何值都将被忽略。
  • UITextField 类还提供了一个用于清除当前文本的内置按钮。因此,如果用户不想要该文本,他可以丢弃它。 myTextField.clearButtonMode = UITextFieldViewModeAlways;
  • 在 Swift 中:textField.clearButtonMode = UITextFieldViewMode.Always
【解决方案2】:

你可以直接调用委托的方法

picker.delegate?.pickerView?(picker, didSelectRow: 0, inComponent: 0)

【讨论】:

    【解决方案3】:
    -(void)textFieldDidBeginEditing:(UITextField *)textField
    {
        // Only for the text field with the picker
        if (textField == self.yourTextField && [textField length]!=0)
        {
            // Select the first row programmatically 
            [self.categoriesPicker selectRow:0 inComponent:0 animated:YES];
            // The delegate method isn't called if the row is selected programmatically
            [self pickerView:self.categoriesPicker didSelectRow:0 inComponent:0];
        }
    
    
    
    }
    
    - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
    {
        //Do all the stuff to populate the TextField
    }
    

    【讨论】:

    • 强制调用代理完成了这项工作
    【解决方案4】:

    您能否在实例化 UIPickerView 后立即以编程方式选择一行?

    int firstRow = 0;
    int firstOptionIndex = 0;
    [myPickerView selectRow:firstRow inComponent:firstOptionIndex animated:NO];
    

    最后一行将触发您的pickerView:didSelectRow:inComponent 委托方法。

    换句话说,应该设置变量的值,无论你在哪里存储它(NSArray? 不清楚)。

    【讨论】:

    • 就可以了。但是假设用户决定在文本字段中输入自定义值。然后决定他毕竟想使用选择器中的第一个值。所以现在 selectText 具有在文本字段中输入的值。用户只需单击第一行,认为他会覆盖在文本字段中输入的值。但这不会发生,因为程序不会知道用户点击了第一个选项。
    • 触摸选择器视图的第一行不会为您生成选择事件可能只是 UIPickerView 设计的“缺点”,因为您需要它才能工作,但这不一定是 UITextField 的问题本身。您可以考虑在bugreporter.apple.com 中提交对 UIPickerView 的功能增强。
    • 我看到了不同的行为。当我按照您的描述以编程方式移动选择器时,我的委托方法不会触发。如果我实际使用 UI 移动选择器,它会按预期触发。对我来说,代表不会开火是有道理的。由于我正在以编程方式移动选择器,因此我知道它已移动,因此我可以立即处理任何所需的更新。
    • 说实话,我给出这个答案已经快九年了。自 2009 年以来,iOS API 和行为很可能发生了一些变化。我建议查看更新的答案——尤其是那些 Swift-ian 的答案。
    【解决方案5】:

    要克服当用户选择列表中的第一项时 UIPickerView 中没有调用 didSelectRow 的问题,您可以使用 UITapGestureRecognizer。 (Swift 中的代码示例)

    self.txtTransType = self.makeTextField(self.transType, placeHolder: "Check-in or Check-out")
    self.txtTransType?.addTarget(self, action: "txtTransTypeEditing:", forControlEvents: UIControlEvents.EditingDidBegin)
    
    func makeTextField(text: String?, placeHolder: String) -> UITextField {
        var textField = UITextField(frame: CGRect(x: 140, y: 0, width: 220.00, height: 40.00));
        textField.placeholder = placeHolder
        textField.text = text
        textField.borderStyle = UITextBorderStyle.Line
        textField.secureTextEntry = false;
        textField.delegate = self
        return textField
    }
    
    func txtTransTypeEditing(sender: UITextField) {
        var ttPickerView:UIPickerView = UIPickerView()
        ttPickerView.dataSource = self
        ttPickerView.delegate = self
        sender.inputView = ttPickerView
    
        let recognizer = UITapGestureRecognizer(target: self, action:Selector("handleTransTypePickerTap:"))
        recognizer.delegate = self
        ttPickerView.addGestureRecognizer(recognizer)
    }
    
    func handleTransTypePickerTap(recognizer: UITapGestureRecognizer) {
        let ttPickerView = recognizer.view as! UIPickerView
        let row = ttPickerView.selectedRowInComponent(0)
        self.txtTransType!.text = self.transTypeData[row]
    }
    

    使用以下链接UIGestureRecognizer Tutorial: Getting Started 让点击识别器工作(需要添加 UIGestureRecognizerDelegate)和以下代码

    class TransactionViewController: UIViewController, UITextFieldDelegate,UIPickerViewDataSource,UIPickerViewDelegate, UIGestureRecognizerDelegate  { }
    
    func gestureRecognizer(UIGestureRecognizer,
        shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) -> Bool {
            return true
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多