表格视图单元格中的文本字段

Posted

技术标签:

【中文标题】表格视图单元格中的文本字段【英文标题】:Text fields in Table View Cells 【发布时间】:2016-06-28 12:46:48 【问题描述】:

我正在开发这个应用程序,而且我是 Swift 新手。只有两周的知识。我应该创建一个包含 12 个单元格的表格视图 - 其中 3 个应该是文本字段,用户可以输入他们想要的内容。我制作了两个具有两个不同标识符的原型单元。我正在使用一个名为“items”的数组,其中包含要在单元格中表示的字符串。如果字符串为空白,则该单元格应该是一个文本字段,我已经这样做了。之后,当我尝试输入这些字段并滚动单元格时,就会出现问题。

请帮助我理解和解决以下问题:

    如何将作为子视图添加的文本字段委托给我的 tableview 单元格? 如何确保我在文本字段中输入的任何内容都保留在那里,即使在我根据需要上下滚动单元格之后也是如此? 如何确保用户可以编辑他们在文本字段中键入的任何内容?

这是我的代码:

    var items = ["Apple", "Fish", "Dates", "Cereal", "Ice cream", "Lamb", "Potatoes", "Chicken", "Bread", " ", " "," "]

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

    var iD = "normal"
    if (items[indexPath.row] == " ") 
        iD = "textField"
        let cell = tableView.dequeueReusableCellWithIdentifier(iD, forIndexPath: indexPath)
        cell.textLabel?.text = items[indexPath.row]

        let textField = UITextField(frame: CGRect(x: 20, y: 10, width: 150, height: 30))
        textField.backgroundColor = UIColor.brownColor()
        textField.placeholder = ""         
        cell.contentView.addSubview(textField)
        return cell      
    
    else 
        let cell = tableView.dequeueReusableCellWithIdentifier(iD, forIndexPath: indexPath)
        cell.textLabel?.text = items[indexPath.row]
        return cell  
    

////

    func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) 
    if (sourceIndexPath.row != destinationIndexPath.row)
        let temp = items[sourceIndexPath.row]
        items.removeAtIndex(sourceIndexPath.row)
        items.insert(temp, atIndex: destinationIndexPath.row)

    
    tableView.reloadData()

【问题讨论】:

您好,欢迎来到 ***。请在每个帖子中保留一个问题,否则a) 将难以创建答案,b) 您将难以选择“正确”答案。 【参考方案1】:

我宁愿创建一个 UITableviewCell 的子类并在那里添加一个文本字段作为子视图。然后将文本字段的委托设置为单元格本身。 这是一些示例代码。我没有尝试运行它,但我认为它应该可以工作:

class InputCell: UITableViewCell, UITextFieldDelegate 

private let textField = UITextField()
private var resultBlock: ((changedText: String) -> ())? = nil

override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    self.textField.delegate = self
    self.contentView.addSubview(self.textField)
    // additional setup for the textfield like setting the textstyle and so on


func setup(initalText: String, resultBlock: (changedText: String) -> ()) 
    self.textField.text = initalText
    self.resultBlock = resultBlock


func textFieldDidEndEditing(textField: UITextField) 
    if let block = self.resultBlock, let text = textField.text 
        block(changedText: text)
    


在您的视图控制器中,我会将项目更改为字典,因此您可以直接将它们链接到 tableview 的索引路径。而且你需要让 tableview 注册你的自定义单元格类。

var items = [0: "Apple", 1: "Fish", 2: "Dates", 3: "Cereal", 4: "Ice cream", 5: "Lamb", 6: "Potatoes", 7: "Chicken", 8: "Bread", 9: " ", 10: " ", 11: " "]

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

    // the position of the cell with a textfield is fixed right? Just put the row number here then
    if indexPath.row > 8 
        let cell = tableView.dequeueReusableCellWithIdentifier("CellWithTextField", forIndexPath: indexPath) as! InputCell
        if let initialText = items[indexPath.row] 
            cell.setup(initialText)  [weak self] text in
                self?.items[indexPath.row] = text
            
        
        return cell
     else 
        let cell = tableView.dequeueReusableCellWithIdentifier("NormalCell", forIndexPath: indexPath)
        cell.textLabel?.text = items[indexPath.row]
        return cell
    

【讨论】:

非常感谢!如何将文本字段的代表连接到单元格本身?我需要在情节提要中创建一个 textField 还是在代码中完成? 在我的示例中,文本字段的委托已经设置(在单元格的 init 中)。此外,文本字段已经存在,您必须对其进行约束或给它一个框架以使其显示【参考方案2】:

首先,添加文本字段协议 UITextFielDelegate,并在行 atindex 的单元格中写入 textfield.delegate = self。

并添加委托方法来管理文本。

希望这对您有所帮助。

【讨论】:

你的意思是在定义类时,我应该调用 UITextFieldDelegate 和 tableview 的那些吗?另外,你能解释一下委托方法吗? like yourclass: UIViewController, UITextFieldDelegate func textFieldDidEndEditing(textField: UITextField) print(textField.text) 谢谢。这就是我所做的: class MainScreen : UIViewController, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate ---- 但我不能调用这些委托函数。如何在我的 cellforRowIndex 函数中使用它们? 在您的文本字段委托方法中,您可以保存您的文本,稍后将它们用于在文本字段中显示或编辑。【参考方案3】:

您必须将文本字段数据保存在某个对象中。由于 UITableView 重用相同的单元格,您的文本字段文本将在滚动时丢失,因为单元格将被重用。我建议为每个 indexPath 创建一些数组并将数据存储在其中。

您应该在单元格类中实现 UITextField 委托方法,并且每当某些文本发生更改时,您应该调用您的另一个委托方法 (CellDelegate),该方法应该在 ViewController 中实现以更新数据。

此委托方法将传递单元格的文本和 indexPath。

【讨论】:

这是我完全迷路的地方。我不知道如何将它存储为某种数组,然后将其链接到那些特定的单元格,这些单元格中的文本是来自文本字段的。您能否为上面建议的所有解决方案提出一些代码示例?【参考方案4】:

在 UITableViewCell 中为 textChange 添加 UItextfield 委托。 您可以更改 items 数组以包含具有实际值和编辑值的模型对象。

let apple = Item()
apple.realValue = "Apple"
apple.editedValue = ""

var item = [0: apple, .............

在表格视图单元格中传递模型对象并在文本更改委托调用上更新编辑值。在 cellForRow 的 textfield 文本属性中添加editedValue

let item = items[indexPath.row]
cell.textLabel?.text = item.realValue
if item.editedValue
// add the textFieldText

【讨论】:

【参考方案5】:

继承 UITextFieldDelegate 给你的控制器

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

var iD = "normal"
if (items[indexPath.row] == " ") 
    iD = "textField"
    let cell = tableView.dequeueReusableCellWithIdentifier(iD, forIndexPath: indexPath)
    cell.textLabel?.text = items[indexPath.row]

    let textField = UITextField(frame: CGRect(x: 20, y: 10, width: 150, height: 30))
    textField.backgroundColor = UIColor.brownColor()
    textField.placeholder = ""         
    cell.contentView.addSubview(textField)
    textField.delegate = self // set delegate
    textField.tag= indexPath.row
    return cell      

else 
    let cell = tableView.dequeueReusableCellWithIdentifier(iD, forIndexPath: indexPath)
    cell.textLabel?.text = items[indexPath.row]
    return cell  
  


 //delegate methods

 func textFieldDidBeginEditing(textField: UITextField!)       //delegate method
  print(textField.tag)//you will get the row. items[textField.tag] will get the object

 
 func textFieldShouldEndEditing(textField: UITextField!) -> Bool    //delegate method
  print(textField.tag)//you will get the row. items[textField.tag] will get the object
  items[textField.tag]= textField.text
  return false


 func textFieldShouldReturn(textField: UITextField!) -> Bool      //delegate method
   textField.resignFirstResponder()
   return true
 

【讨论】:

我应该在哪里使用这些委托方法?在我的 cellForRowIndex 函数中? 你能给我一个例子,说明我如何将文本字段和单元格文本链接在一起吗?同一个控制器,你的意思是类吗? 你的单元格是动态的吗?您需要标记文本字段。 你应该设置一个标签来识别哪一行文本字段被编辑。我会更新 我按照你的建议做了。但它只在一个文本字段中进行编辑。不是他们三个。它让我可以选择三个字段中的任何一个进行编辑,但是一旦我开始编辑,它就不允许我编辑任何其他字段。有什么问题?

以上是关于表格视图单元格中的文本字段的主要内容,如果未能解决你的问题,请参考以下文章

自定义表格视图单元格中的可编辑文本字段

如何在编辑表格视图单元格中的文本字段时重新加载所有表格视图单元格 - iOS Swift

根据在单元格中的文本字段中输入的值动态增加表格视图单元格

表格视图单元格中的标签和文本字段之间的空间相等。

点击保存按钮并存储在字典中时获取表格视图单元格中的文本字段?

移动到表格单元格中的下一个文本字段