xcode 如何让用户修改 UITableView 单元格中的文本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8858228/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to let user to modify the text in UITableView cells
提问by jessy
I have a question regarding uitable view.
我有一个关于适用视图的问题。
I am implementing an app which is similar to the address book app.I am able to present the table view in editing mode. I want to let the user to edit the text in the cells in editing mode. I know that in order to edit the text in the cells, I need a textfield. I have created a textfield.
我正在实现一个类似于地址簿应用程序的应用程序。我能够在编辑模式下显示表格视图。我想让用户在编辑模式下编辑单元格中的文本。我知道为了编辑单元格中的文本,我需要一个文本字段。我创建了一个文本字段。
My question is:
我的问题是:
what should I do in order to present that textfield in the cells.
what are the methods I need to implement in order to present that text field in the table view in editing mode.
Once I am done with editing ,How can I update the data which is in my contacts view controller(contains all the contacts).The saving should persist in the address book. For this question I know that I need to implement some delegate method,But I am not sure how to do that.
我应该怎么做才能在单元格中显示该文本字段。
为了在编辑模式下在表格视图中显示该文本字段,我需要实现哪些方法。
完成编辑后,如何更新我的联系人视图控制器中的数据(包含所有联系人)。保存的内容应保留在地址簿中。对于这个问题,我知道我需要实现一些委托方法,但我不知道该怎么做。
Please have a look at the following code,so that you will have an idea about my problem.
请查看以下代码,以便您对我的问题有所了解。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
[tableView setSeparatorColor:[UIColor clearColor]];
//[self.tableView setEditing: YES animated: YES];
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
if(isEditingOn) {
if(cell == nil)
cell = [self getCellContentView:CellIdentifier];
UILabel *lblTemp1 = (UILabel *)[cell viewWithTag:1];
UITextField *textfield1=(UITextField*)[cell viewWithTag:2];
if(indexPath.row == 0) {
lblTemp1.text = @"Name";
textfield1.text = myContact.name;
}
else if(indexPath.row == 1) {
lblTemp1.text = @"Phone";
textfield1.text = myContact.phone;
}
else if(indexPath.row == 2) {
lblTemp1.text = @"Email";
textfield1.text = myContact.email;
}
}
else {
if(indexPath.row == 0) {
cell.textLabel.text = myContact.name;
}
else if(indexPath.row == 1) {
cell.textLabel.text = myContact.phone;
}
else if(indexPath.row == 2) {
cell.textLabel.text = myContact.email;
}
}
return cell;
}
}
- (UITableViewCell *) getCellContentView:(NSString *)cellIdentifier {
CGRect CellFrame = CGRectMake(0, 0, 60, 20);
CGRect Label1Frame = CGRectMake(10, 10, 180, 25);
UILabel *lblTemp;
UITableViewCell *cell = [[[UITableViewCell alloc] initWithFrame:CellFrame reuseIdentifier:cellIdentifier] autorelease];
lblTemp = [[UILabel alloc] initWithFrame:Label1Frame];
lblTemp.tag = 1;
[cell.contentView addSubview:lblTemp];
[lblTemp release];
CGRect TextFieldFrame=CGRectMake(240, 10, 60, 25);
UITextField *textfield;
textfield=[[UITextField alloc]initWithFrame:TextFieldFrame];
textfield.tag=2;
textfield.placeholder = @"";
[cell.contentView addSubview:textfield];
}
回答by Nick Lockwood
This is a really complex question to answer this fully and in-depth with code examples, but I'll try to point you in the right direction.
这是一个非常复杂的问题,要通过代码示例全面深入地回答这个问题,但我会尽力为您指明正确的方向。
1) Add a UITextField as a subview of your table cell when you create the cell in the tableView:cellForRowAtIndexPath: method (I assume that's what your getCellContentView: method is for). Set a tag on your UITextField that matches the row index of the cell and make your tableviewcontroller the delegate for the cell. Set the textfield to hidden. (remember to set the tag each time the cell is requested, not just the first time you create it).
1)当您在 tableView:cellForRowAtIndexPath: 方法中创建单元格时,添加一个 UITextField 作为表格单元格的子视图(我假设这就是您的 getCellContentView: 方法的用途)。在您的 UITextField 上设置一个与单元格的行索引匹配的标签,并使您的 tableviewcontroller 成为该单元格的委托。将文本字段设置为隐藏。(记住每次请求单元格时都设置标签,而不仅仅是第一次创建它时)。
2) In the tableView:didSelectRowAtIndexPath: method, grab the cell using tableViewCellForRowAtIndexPath and then show the textfield inside it (you may have to do some view traversal to get it) and call becomeFirstResponder on the textfield.
2) 在 tableView:didSelectRowAtIndexPath: 方法中,使用 tableViewCellForRowAtIndexPath 抓取单元格,然后在其中显示文本字段(您可能需要进行一些视图遍历才能获取它)并在文本字段上调用 becomeFirstResponder。
3) When the user has typed something, your textfielddelegate methods will be fired. You can look at the tag on the textfield to work out which row the field belongs to and then update the dat source with the new text. Then just reload the table to hide the textfield and update the cell content.
3) 当用户输入内容时,您的 textfielddelegate 方法将被触发。您可以查看文本字段上的标记以确定该字段属于哪一行,然后使用新文本更新数据源。然后只需重新加载表格以隐藏文本字段并更新单元格内容。
If you know how to use custom table cell subclasses then you can make your life a bit easier by creating a custom cell that already contains a textfield and has an property for accessing it, but otherwise the technique will be mostly the same.
如果您知道如何使用自定义表格单元格子类,那么您可以通过创建一个已经包含文本字段并具有访问它的属性的自定义单元格让您的生活更轻松,但除此之外,技术将大体相同。
Also, tableView:didSelectRowAtIndexPath: won't normally fire when a tableview is in edit mode unless you set tableView.allowsSelectionDuringEditing = YES;
此外,除非您设置 tableView.allowsSelectionDuringEditing = YES,否则 tableView:didSelectRowAtIndexPath: 通常不会在 tableview 处于编辑模式时触发。
回答by wajih
It's better to use 2 UITableViewCell
s, The first one for view
and the last for edit
mode.
最好使用 2 UITableViewCell
s,第一个 forview
和最后一个 foredit
模式。
Also we will depend on the variable rowToEdit
which refers to the current editing row. (in my case one cell is allowed to be edited at the same time)
此外,我们将依赖于rowToEdit
引用当前编辑行的变量。(在我的情况下,允许同时编辑一个单元格)
let us begin:
让我们开始:
First I depend on
accessoryButtonTap
action to edit the row:var rowToEdit: IndexPath? = nil override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) { // End edit mode if one cell being in edit mode other than this one if let row = self.rowToEdit { // return current edit cell to view mode self.rowToEdit = nil self.tableView.reloadRows(at: [row], with: .automatic) } self.rowToEdit = indexPath self.tableView.reloadRows(at: [self.rowToEdit!], with: .automatic) }
Differentiate between the 2 modes when you will load the cell:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { if indexPath == self.rowToEdit { let cellId = "ContactEditTableViewCell" let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath as IndexPath) as! ContactEditTableViewCell cell.accessoryType = .none self.configEditCell(cell: cell, indexPath: indexPath) return cell } else { let cellId = "ContactTableViewCell" let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath as IndexPath) as! ContactTableViewCell self.configCell(cell: cell, indexPath: indexPath) return cell } }
Additional option if you want to change the height based on mode:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { if indexPath == self.rowToEdit { return 120 } else { return 70 } }
Last option to add
Save
andCancel
buttons: I added them to eachcell
, So I pass a reference to theContactTable
to each cell.@IBAction func btnSave_click(_ sender: UIButton) { // save the record btnCancel_click(sender) } @IBAction func btnCancel_click(_ sender: UIButton) { let tmp = self.tbl.rowToEdit self.tbl.rowToEdit = nil self.tbl.tableView.reloadRows(at: [tmp!], with: .automatic) }
首先,我依靠
accessoryButtonTap
操作来编辑该行:var rowToEdit: IndexPath? = nil override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) { // End edit mode if one cell being in edit mode other than this one if let row = self.rowToEdit { // return current edit cell to view mode self.rowToEdit = nil self.tableView.reloadRows(at: [row], with: .automatic) } self.rowToEdit = indexPath self.tableView.reloadRows(at: [self.rowToEdit!], with: .automatic) }
加载单元格时区分两种模式:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { if indexPath == self.rowToEdit { let cellId = "ContactEditTableViewCell" let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath as IndexPath) as! ContactEditTableViewCell cell.accessoryType = .none self.configEditCell(cell: cell, indexPath: indexPath) return cell } else { let cellId = "ContactTableViewCell" let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath as IndexPath) as! ContactTableViewCell self.configCell(cell: cell, indexPath: indexPath) return cell } }
如果您想根据模式更改高度,则附加选项:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { if indexPath == self.rowToEdit { return 120 } else { return 70 } }
添加
Save
和Cancel
按钮的最后一个选项:我将它们添加到 eachcell
,所以我将引用传递ContactTable
给每个单元格。@IBAction func btnSave_click(_ sender: UIButton) { // save the record btnCancel_click(sender) } @IBAction func btnCancel_click(_ sender: UIButton) { let tmp = self.tbl.rowToEdit self.tbl.rowToEdit = nil self.tbl.tableView.reloadRows(at: [tmp!], with: .automatic) }