2017-06-22 79 views
0

UITableView约20行均含有一UITextField。第一次点击一个文本框会打开键盘,我准备编辑这个文本框。如果我点击下一个文本框(注意键盘始终显示),键盘仍然显示,但蓝色光标不在新文本框中,我无法输入任何文本。但是如果我再次点击另一个文本框,它就可以正常工作。这种行为交替发生,一次它工作而另一次不工作。的UITextField中的UITableView不成为第一个响应者

委托方法textFieldShouldBeginEditing(_:)总是被调用,阉我可以编辑或没有。代理方法textFieldDidBeginEditing(_:)仅在编辑工作时调用。

这是cellForRowAt

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: "TextFieldCell")! 
    let titleLabel = cell.viewWithTag(1) as! UILabel 
    let contentTextField = cell.viewWithTag(2) as! FixableTextField 
    contentTextField.delegate = self 
    contentTextField.inputAccessoryView = doneToolbar 

    // Enable/disable editing for text fields 
    if isEditing { 
     contentTextField.enableEditing() 
    } else { 
     contentTextField.disableEditing() 
    } 

    // Present Profile Data 
    if profileUpdateBuffer != nil { 

     switch indexPath.row { 
     case 0: 
      titleLabel.text = "Count" 
      contentTextField.text = "\(profileUpdateBuffer!.count)" 
      contentTextField.purposeID = "count" 
      contentTextField.keyboardType = .numberPad 

     case 1: 
      titleLabel.text = "City" 
      contentTextField.text = "\(profileUpdateBuffer!.city)" 
      contentTextField.purposeID = "city" 
      contentTextField.keyboardType = .default 

     // ... 

     case 20: 
      titleLabel.text = "Name" 
      contentTextField.text = "\(profileUpdateBuffer!.name)" 
      contentTextField.purposeID = "name" 
      contentTextField.keyboardType = .default 

     default: 
      titleLabel.text = "" 
      contentTextField.text = "" 
     } 

     return cell 
    } 

    // No data available -> show info in first row 
    else { 
     if indexPath.row == 0 { 
      titleLabel.text = "No data" 
      contentTextField.text = "No data" 
     } 
     else { 
      titleLabel.text = "" 
      contentTextField.text = "" 
     } 
     return cell 
    } 
} 

enableEditing()disableEditing()方法的代码是从FixableTextField类。我可以看到文本框始终处于启用状态,因为我可以看到文本框边框

// Extract from FixableTextField class 
func enableEditing() { 
    self.isEnabled = true 
    self.borderStyle = .roundedRect 
} 

func disableEditing() { 
    self.isEnabled = false 
    self.borderStyle = .none 
} 

代码从setProperty方法,它是从ProfileDataUITextField

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { 

    // Delete empty field indicator "-" 
    if textField.text == "-" { 
     textField.text = "" 
    } 

    //Move profileTable's contentView to correct position 
    if textField is FixableTextField { 
     let path = IndexPath(row: rowMap[(textField as! FixableTextField).purposeID]!, section: 0) 
     moveContentViewUp(indexPath: path) 
    } 
    return true 
} 



func textFieldDidEndEditing(_ textField: UITextField) { 

    // Save new value to profileUpdateBuffer 
    do { 
     try self.profileUpdateBuffer?.setProperty(value: textField.text!, key: (textField as! FixableTextField).purposeID) 
    } catch ProfileError.PropertySettingWrongType { 
     let falseInputAlert = UIAlertController(title: "False Input", message: "The input for this field is not valid.", preferredStyle: .alert) 
     falseInputAlert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil)) 
     self.present(falseInputAlert, animated: true, completion: nil) 
    } catch { 
     print("Error when trying to set property for profileUpdateBuffer in ProfileViewController") 
    } 

    // Display new data in table 
    profileTable.reloadData() 
} 

提取物。 profileUpdateBuffer的类型是ProfileData

func setProperty(value:String, key:String) throws { 
    switch key { 
    case "count": 
     count = value 

    case "city": 
     count = value 

    // ... 

    case "name": 
     name = value 

    default: 
     throw ProfileError.PropertySettingWrongType 
    } 
} 
+0

请发布您的代码,以便我们可以帮助您。尤其是你的cellForRowAt indexPath函数。你如何添加监听器到你的textFields? –

+0

谢谢,当然我会的。 – Codey

+0

'textFieldShouldBeginEditing(_ :)'中是否有过滤逻辑?我看到你也有你的VC设置为所有文本字段的代表。你有一个逻辑来区分委托方法实现中的单元格吗?您可以尝试在单元格中移动TextField委托,这样每个单元格都将负责自己。 – kr45ko

回答

1

我做了一个小程序来模仿你所描述的行为。 看来问题是由表视图的数据在你textFieldDidEndEditing(_:)年底重装造成的:

func textFieldDidEndEditing(_ textField: UITextField) { 

    // Save new value to profileUpdateBuffer 
    do { 
     try self.profileUpdateBuffer?.setProperty(value: textField.text!, key: (textField as! FixableTextField).purposeID) 
    } catch ProfileError.PropertySettingWrongType { 
     let falseInputAlert = UIAlertController(title: "False Input", message: "The input for this field is not valid.", preferredStyle: .alert) 
     falseInputAlert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil)) 
     self.present(falseInputAlert, animated: true, completion: nil) 
    } catch { 
     print("Error when trying to set property for profileUpdateBuffer in ProfileViewController") 
    } 

    // Display new data in table 
    profileTable.reloadData() 
} 

试用实验的目的去除profileTable.reloadData()确认问题的根本原因(是的,你的其他细胞不会更新)。要解决这个

一种方式是通过利用textFieldDidEndEditing(_:)visibleCells直接的细胞更新。我看到profileUpdateBuffer?是你的数据模型。如果它们在表视图的可见单元格属性中,只需手动从模型更新单元格的titleLabel和textField属性即可。

如果要相应地调整单元格的大小,请将AutoLayout和UITableViewAutomaticDimension用于表视图行高度与beginUpdates()/endUpdates()调用的组合。

有关如何实现直接的细胞操纵和/或动态单元尺寸更新而不失去我已经回答了键盘焦点check the accepted answer on this question更多细节。

希望这会有所帮助!

+0

非常感谢您的详细解答。你是对的,当我删除'profileTable.reloadData()'它工作得很好。我通过更新没有'realodData'的单元格来解决它,就像你说的那样,现在一切正常。你有解释为什么这种行为发生在使用'reloadData'时? – Codey

+1

当您启动'reloadData()'时,表视图禁用用户交互。然后单元格将为'becomeFirstResponder()'返回false。在你的情况下,第二个单元不会成为第一响应者。如果你选择一个新的单元格,没有'reloadData()'调用,因为前一个单元格不会成为第一个响应者,因此不调用didEndEditing()(重新加载所在的位置)。这就是为什么第三个单元格可以编辑的原因。我不确定当编辑不可用时为什么键盘保持在屏幕上 - 我期待在先前的文本字段退出第一响应者时它被解散。 – kr45ko

+0

完美的解释。非常感谢! – Codey

0

我认为,问题是,你调用profileTable.reloadData()......你或许应该只重装一个细胞。也许textFieldDidEndEditing(:)用旧的TextField作为参数被调用,接着是新的TextField的textFieldShouldBeginEditing( :)。的问题是,在刷新所有细胞在textFieldDidEndEditing的端部(:),这意味着由该系统作为参数传递到textFieldShouldBeginEditing TextField的( :)可能不是必需的是相应的单元格中包含的同一个.. 。这些新的击键可能被发送到属于可重复使用单元队列中的单元的TextField,即不可见,但仍然存在于内存中某处。

相关问题