2017-06-22 46 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,即不可見,但仍然存在於內存中某處。

相關問題