Having a Uitextfield in a Uitableviewcell

Accessing UITextField in a custom UITableViewCell

I think what the OP is trying to understand is how to access the UITextField value once the user has entered data into each fields. This will not be available at the time the cells are created as suggested by @willcodejavaforfood.

I've been implementing a form and trying to make it as user friendly as possible. It is doable but be aware that it can get quite convoluted depending on the number of UITableViewCells / UITextFields you have.

Firstly to your question re: accessing the values of UITextField:

1) Make your view controller a <UITextFieldDelegate>

2) Implement the following method:

- (void) textFieldDidEndEditing:(UITextField *)textField {
NSIndexPath *indexPath = [self.tableView indexPathForCell:(CustomCell*)[[textField superview] superview]]; // this should return you your current indexPath

// From here on you can (switch) your indexPath.section or indexPath.row
// as appropriate to get the textValue and assign it to a variable, for instance:
if (indexPath.section == kMandatorySection) {
if (indexPath.row == kEmailField) self.emailFieldValue = textField.text;
if (indexPath.row == kPasswordField) self.passwordFieldValue = textField.text;
if (indexPath.row == kPasswordConfirmField) self.passwordConfirmFieldValue = textField.text;
}
else if (indexPath.section == kOptionalSection) {
if (indexPath.row == kFirstNameField) self.firstNameFieldValue = textField.text;
if (indexPath.row == kLastNameField) self.lastNameFieldValue = textField.text;
if (indexPath.row == kPostcodeField) self.postcodeFieldValue = textField.text;
}
}

I also use a similar syntax to make sure the current edited field is visible:

- (void) textFieldDidBeginEditing:(UITextField *)textField {
CustomCell *cell = (CustomCell*) [[textField superview] superview];
[self.tableView scrollToRowAtIndexPath:[self.tableView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}

And finally, you can handle textViewShouldReturn: in a similar way:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
NSIndexPath *indexPath = [self.tableView indexPathForCell:(CustomCell*)[[textField superview] superview]];
switch (indexPath.section) {
case kMandatorySection:
{
// I am testing to see if this is NOT the last field of my first section
// If not, find the next UITextField and make it firstResponder if the user
// presses ENTER on the keyboard
if (indexPath.row < kPasswordConfirmField) {
NSIndexPath *sibling = [NSIndexPath indexPathForRow:indexPath.row+1 inSection:indexPath.section];
CustomCell *cell = (CustomCell*)[self.tableView cellForRowAtIndexPath:sibling];
[cell.cellTextField becomeFirstResponder];
} else {
// In case this is my last section row, when the user presses ENTER,
// I move the focus to the first row in next section
NSIndexPath *sibling = [NSIndexPath indexPathForRow:kFirstNameField inSection:kOptionalSection];
MemberLoginCell *cell = (MemberLoginCell*)[self.memberTableView cellForRowAtIndexPath:sibling];
[cell.cellTextField becomeFirstResponder];
}
break;
}
...
}

obtain data from UITextField in UITableViewCell

I would suggest you to try something like I wrote in this gist for you (the source is for interactive playground).

Briefly, I suggest introducing a model for your data:

class Model {

let placeholder: String?
var text: String?

init(placeholder: String?, text: String? = nil) {
self.placeholder = placeholder
self.text = text
}

}

Then making a list of models to actually store the data:

// Sample items.
let items = [
TextFieldCell.Model(placeholder: "1"),
TextFieldCell.Model(placeholder: "2"),
TextFieldCell.Model(placeholder: "3", text: "xxx"),
TextFieldCell.Model(placeholder: "4"),
TextFieldCell.Model(placeholder: "5"),
TextFieldCell.Model(placeholder: "6")
]

And connecting visible cells to the corresponding models via an appropriate data source.

The cell may be like this:

class TextFieldCell: UITableViewCell, SmartCell, UITextFieldDelegate {

var model: Model? {
didSet {
textField.placeholder = model?.placeholder
textField.text = model?.text
}
}

let textField = UITextField()

required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}

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

private func commonInit() {
contentView.addSubview(textField)
textField.delegate = self
}

override func layoutSubviews() {
textField.frame = contentView.bounds.insetBy(dx: 15, dy: 8)
}

func loadModel(m: Model) {
model = m
}

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let text = (textField.text as NSString?)?.stringByReplacingCharactersInRange(range, withString: string)
// Update the model.
model?.text = text
return true
}
}

After that, you can read the data entered by user at any time from the list of the models.

Play with the gist in an interactive iOS playground!

getting value from uitextfield in uitableview

I have resolved my problem like follows.

I have created a unique ID for my Datasource and i use that to determine with cell has been updated.

var row = 0
var section = 0

for var k = 0; k < fieldsWSections.count; k++ {
for var kk = 0; kk < fieldsWSections[k].count; kk++ {
if fieldsWSections[k][kk].ID == String(textField.tag) {
section = k
row = kk
}
}
}

if data[fieldsWSections[section][row].name] != textField.text {
newData[fieldsWSections[section][row].ID] = textField.text
}

So i don't need to know the indexPath anymore.

How to properly add UITextField to UITableViewCell

Create a custom UITableView cell as a xib and make a corresponding .swift file for this. Add a textField to the cell and create an IBOutlet for the textField in the custom .swift class. Make sure your constraints are set in this xib.

In your ViewController .swift class, make the func tableView(cellForRowAtIndexPath) return your custom cell.

You do not have to set the firstResponder because the keyboard will come up by default. Unless of your cell is basically just a textField, it doesn't seem wise to have the didSelectRowAtIndexPath to always bring up the keyboard. If, for some reason that the cell always takes the touch action, then use didSelectRowAtIndexPath, but use

tableView.cellForRowAtIndexPath(indexPath).textField.becomeFirstResponder()

Set textField delegate to the custom cell and add this in the CustomTableViewCell.swift to dismiss the keyboard upon press of return key:

func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return false
}

Side note: The keyboard will not show in the simulator unless you deselected the option to use the hardware keyboard.

Here is a sample project with what I think you are trying to achieve:
https://mega.nz/#!B1ASDIQT!8-diyv_Fd2H66nb08gs3ObzlQqVHKUUIs4U_BbI6s4s

How to connect UITextField to UITableView?

You can Not directly Connect outlet of Any Thing Embedded In TableCell

Follow Steps To Perform Code operation with Outlets Connected

Step 1- Create a new tableViewCell Class as Below ScreenSHot

Sample Image

Step 2- Now Assign Created Class to TableView cell in Storyboard as Below

Sample Image

Step 3- Time to connect outlets in Cell class created by normally dragging the TF to be Connected in cell class

output will be as Below

Sample Image

Step 4- Required Coding

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomTableCell

cell.fileNameLabel.text = coreClassObject.audioFileName
cell.durationLabel.text = coreClassObject.audioDuration
cell.uploadedStatusLabel.text = coreClassObject.audioUploadStatus

cell.playButton.addTarget(self, action: #selector(playSoundAtSelectedIndex(sender:)), for: .touchUpInside)
return cell
}

Re-Update Answer to Access TF in ViewDidLoad

----> my ViewController class

import UIKit

class tableViewVC: UIViewController
{

let staticArrayy = ["1","1","1","1","1","1","1","1","1","1"]

@IBOutlet weak var myDemoTableView: UITableView!

override func viewDidLoad()
{
super.viewDidLoad()

// Do any additional setup after loading the view.

///Set Delegates
myDemoTableView.delegate = self
myDemoTableView.dataSource = self

///Async operation
///To make sure cells are loaded
DispatchQueue.main.async
{
///Create a Reference TF
let MyTf : UITextField!

///Get Index Path of Which TF is to be Accessed
let indexPath = IndexPath(row: 0, section: 0)

///Create A new cell Reference
let newCell = self.myDemoTableView.cellForRow(at: indexPath)! as! CustomTableViewCell

///Assign Cell TF to our created TF
MyTf = newCell.cellTF

///Perform Changes
MyTf.text = "Changes text"
}

}
}

extension tableViewVC : UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return staticArrayy.count
}

//Setting cells data
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = self.myDemoTableView.dequeueReusableCell(withIdentifier: "Cell") as! CustomTableViewCell
cell.cellTF.placeholder = staticArrayy[indexPath.row]
return cell
}

//Setting height of cells
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return 60
}
}

---> My cell class

import UIKit

class CustomTableViewCell: UITableViewCell
{

@IBOutlet weak var cellTF: UITextField!

override func awakeFromNib()
{
super.awakeFromNib()
// Initialization code
}

override func setSelected(_ selected: Bool, animated: Bool)
{
super.setSelected(selected, animated: animated)

// Configure the view for the selected state
}

}

----> My StoryBoard

Sample Image

---> Simulator Output

Sample Image

Get uitextfield data from custom uitableview cell - Swift

First issue -- in your cell class, in awakeFromNib() you have:

// CREATE a UITextField
var textField = UITextField()
var data: Dictionary<String, Any>?

override func awakeFromNib() {
super.awakeFromNib()

// assign self as the delegate of textField
textField.delegate = self

let padding = UIView(frame: CGRect(x:0, y:0, width: 15, height: self.frame.height))

// CREATE a NEW UITextField
textField = UITextField(frame: CGRect(x:0, y:0, width: self.frame.width, height: 40))

So, when you create the NEW textField, it no longer has a delegate assigned to it. That's why nothing triggers textFieldShouldReturn or textFieldDidEndEditing.

Replace the UITextField(frame: ..) line with:

    textField.frame = CGRect(x:0, y:0, width: self.frame.width, height: 40)

Next, instead of passing in a "data object" to then try and manipulate, think about using a call-back closure.

Change your cell class to this:

class RTextCell: UITableViewCell, UITextFieldDelegate {

var textField = UITextField()

// this will be our "call back" closure
var didEndEditAction : ((String)->())?

override func awakeFromNib() {
super.awakeFromNib()

textField.delegate = self

let padding = UIView(frame: CGRect(x:0, y:0, width: 15, height: self.frame.height))

// just set the frame, don't create a NEW textField
textField.frame = CGRect(x:0, y:0, width: self.frame.width, height: 40)
textField.placeholder = "Your text here"
textField.textColor = UIColor.white
textField.tintColor = UIColor.white
textField.backgroundColor = UIColor.clear
textField.leftView = padding
textField.leftViewMode = .always

self.addSubview(textField)

}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
print("Should return")
return true
}

func textFieldDidEndEditing(_ textField: UITextField) {
// call back using a closure
didEndEditAction?(textField.text ?? "")
}

}

And then configure it like this:

    case "textbox":
let rTemplateTextBox = tableView.dequeueReusableCell(withIdentifier: "recapTextCell", for: indexPath) as! RTextCell
rTemplateTextBox.textField.text = cell["data"] as? String ?? "No text"

// setup the "call back" closure
rTemplateTextBox.didEndEditAction = {
(newText) in
let cell = self.myData[indexPath.row]
cell["data"] = newText
}

return rTemplateTextBox


Related Topics



Leave a reply



Submit