how I should set text into my textfield that is on tableview? - swift

i have this problem, I have a table view with a custom cell, the custom cell has a text field, I should put text in this textfield with a custom button, the button is out of the tableview.
my problem is, how I can set text into textfield? and my other problem is that I can't identify the current textfield for set text, I only know the tag.
this is my code
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! budgetCellTableViewCell
cell.insertText.delegate = self
cell.insertText.tag = indexPath.row
cell.insertText.inputView = UIView()
cell.showViews()
if let money = arrayData[indexPath.row]["amount"]
{
cell.showSubtitle.text = "Ultimos 30 dias: \(money)"
}
if let cat = arrayData[indexPath.row]["category"]
{
cell.showTitle.text = cat as? String
}
cell.selectionStyle = .none
return cell
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if self.textFieldTagActive == textField.tag
{
textField.text = setText
}
else
{
self.setText = ""
self.textFieldTagActive = textField.tag
}
func addNumber(_ number: Int) {
if number != -1
{
setText += String(number)
}
else
{
setText.removeLast()
}
}
the function addNumber is used when I push my custom button
with the function textFieldDidBeginEditing I get the textfield tag, I push my custom button and finally I push the same textfield and the text appears in the textfield, but I really want push my button and the same time, the text appears into textfield
so, how I can set text into my textfield since my custom button that is out of tableview?
thanks

you can get the current text field from delegate functions.
class ViewController: UIViewController {
var currentText = "your text"
var currentTF: UITextField?
#IBAction func buttonTapped(_ sender: Any) {
// set text to the text field.
currentTF?.text = currentText
}
}
extension ViewController: UITextFieldDelegate {
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
// get the text field that you want
currentTF = textField
return true
}
}

Related

How to simultaneously change textField.text in a prototype cell?

I have a UITableViewController and a Prototype cell with a UITextField. When I change a textField.text in one of the cells I want it to be changed in all other cells which my tableView now have (for example multiply number by 2 and set to other cell's textField.text output).
This is the behaviour I want to implement: CLICK
Should I trigger a certain textField delegate method or it should be made in another way?
My code for now:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cell.numberTextField.delegate = self
}
//Delegate methods
func textFieldDidBeginEditing(_ textField: UITextField) {
textField.text = ""
textField.textColor = UIColor.systemBlue
}
func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) {
textField.text = "0"
textField.textColor = UIColor.black
}
At a high level:
You need to have a model to store your data being updated
You need to observe the text being entered using UITextFieldDelegate
As your text is being entered, update all rows except active cell with new calculations
The most interesting work is in textFieldDidChangeSelection and cellForRowAt indexPath
Here is an example of how I would do something like this:
1. Set up some custom types
// Your model to store data in text fields
// Maybe for you, you will store currencies
// and base currency to multiply against
// I am just storing a random number for example
struct FinanceModel
{
var number: Int?
}
// Custom UITextField which will store info
// about cell index path as we need to identify
// it when editing
class MappedTextField: UITextField
{
var indexPath: IndexPath!
}
2. Example of UITableView Cell, you can ignore if you have your own
fileprivate class CustomCell: UITableViewCell
{
// Use custom text field
var textField: MappedTextField!
static let tableViewCellIdentifier = "cell"
override init(style: UITableViewCell.CellStyle,
reuseIdentifier: String?)
{
super.init(style: style,
reuseIdentifier: reuseIdentifier)
configureTextField()
}
required init?(coder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
// Configure text field and auto layout
private func configureTextField()
{
textField = MappedTextField()
textField.keyboardType = .numberPad
textField.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(textField)
textField.layer.borderWidth = 2.0
textField.layer.borderColor = UIColor.blue.cgColor
textField.layer.cornerRadius = 5.0
// auto-layout
textField.leadingAnchor.constraint(equalTo: contentView.leadingAnchor,
constant: 20).isActive = true
textField.trailingAnchor.constraint(equalTo: contentView.trailingAnchor,
constant: -20).isActive = true
textField.topAnchor.constraint(equalTo: contentView.topAnchor,
constant: 20).isActive = true
textField.bottomAnchor.constraint(equalTo: contentView.bottomAnchor,
constant: -20).isActive = true
}
}
3. Set up in view controller - you can skip if already set up, just here for completeness
class InputViewController: UIViewController
{
let tableView = UITableView()
// Initialize your mode
var financeModel = FinanceModel()
// This will store current editing cell which is active
var activeTextFieldIndexPath: IndexPath?
override func viewDidLoad()
{
super.viewDidLoad()
// This is just view set up for me,
// You can ignore this
title = "TableView Input"
navigationController?.navigationBar.tintColor = .white
view.backgroundColor = .white
configureTableView()
}
// Configure TableView and layout
private func configureTableView()
{
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.register(CustomCell.self,
forCellReuseIdentifier: CustomCell.tableViewCellIdentifier)
tableView.dataSource = self
tableView.delegate = self
// remove additional rows
tableView.tableFooterView = UIView()
view.addSubview(tableView)
// Auto layout
tableView.leadingAnchor
.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
tableView.topAnchor
.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
tableView.trailingAnchor
.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
tableView.bottomAnchor
.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
}
}
4. TableView DataSource
extension InputViewController: UITableViewDataSource
{
func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int
{
// Random number for me
return 10
}
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell =
tableView.dequeueReusableCell(withIdentifier:
CustomCell.tableViewCellIdentifier)
as! CustomCell
// Set index path of custom text field
cell.textField.indexPath = indexPath
// Set view controller to respond to text field events
cell.textField.delegate = self
// Check if any cell is currently active
// && if we are current cell is NOT the active one
// We want to leave active cell untouched
if let activeTextFieldIndexPath = activeTextFieldIndexPath,
activeTextFieldIndexPath.row != indexPath.row
{
updateCell(cell, atIndexPath: indexPath)
}
else
{
// no active cell, just set the text
updateCell(cell, atIndexPath: indexPath)
}
return cell
}
private func updateCell(_ cell: CustomCell,
atIndexPath indexPath: IndexPath)
{
// Retrieve number currently stored in model
if let number = financeModel.number
{
// Set text of number in model * row number
// Do any calculation you like, this is just an
// example
cell.textField.text =
"\(number) x \(indexPath.row) = \(number * indexPath.row)"
}
else
{
// If no valid number, set blank
cell.textField.text = ""
}
}
}
5. TextField Delegate
extension InputViewController: UITextFieldDelegate
{
// Respond to new text in the text field
func textFieldDidChangeSelection(_ textField: UITextField)
{
// 1. Convert generic UITextField to MappedTextField
// 2. && Retrieve index path from custom MappedTextField
// 3. && Retrieve text from the text field
// 4. && Check if text is valid number
if let textField = textField as? MappedTextField,
let indexPath = textField.indexPath,
let text = textField.text,
let number = Int(text)
{
// Assign local variable with index path we are editing
activeTextFieldIndexPath = indexPath
// Update number in the financial model
financeModel.number = number
// We only want to update data in visible rows so
// get all the index paths of visible rows
let visibleRows = self.tableView.indexPathsForVisibleRows ?? []
// We want to update all rows EXCEPT active row
// so do a filter for this
let allRowsWithoutActive = (visibleRows).filter
{
// Remove the active index path from the
// visible index paths
$0.section != indexPath.section ||
$0.row != indexPath.row
}
// Reload the visible rows EXCEPT active
self.tableView.reloadRows(at: allRowsWithoutActive,
with: .automatic)
}
}
// This is just to make current text field
// empty when editing, you can ignore
func textFieldDidBeginEditing(_ textField: UITextField)
{
textField.text = ""
}
// Reset when text field is no longer being edited
func textFieldDidEndEditing(_ textField: UITextField)
{
activeTextFieldIndexPath = nil
tableView.reloadData()
}
}
6. TableView Delegate
extension InputViewController: UITableViewDelegate
{
func scrollViewDidScroll(_ scrollView: UIScrollView)
{
// End editing when scrolling table view
// This is for me, you can have another way
view.endEditing(true)
}
func tableView(_ tableView: UITableView,
heightForRowAt indexPath: IndexPath) -> CGFloat
{
// Return a random height
return 80
}
}
End result is something like this:
Hope this gives you enough to set you on your way.
inside your textFieldDidBeginEditing and textFieldDidChangeSelection delegates, call tableView.reloadData()

How to move curser from one textfield to another in a tableview Form in iOS?

I have a Form that is to be made using a tableview. Each cell have a textfield and I want my cursor to move into next textfield when I tap "next" in keyboard.
here is the tableview code I m using currently:
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.arrayData.count;
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tblView.dequeueReusableCell(withIdentifier: "cellTextField")! as! cellTextField
cell.tfValue.placeholder = objclsSignup.placeHolder! as String
cell.tfValue.tag = indexPath.row
cell.tfValue.delegate = self
cell.tfValue.returnKeyType = UIReturnKeyType.next
if indexPath.row == 6 {
cell.tfValue.returnKeyType = UIReturnKeyType.done
}
return cell
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField.returnKeyType == UIReturnKeyType.next{
textField.becomeFirstResponder()
}else {
textField.resignFirstResponder()
}
return true
}
I am using swift 4, Xcode 10.2.
First, instead of passing data with tags, use delegates in the cell like described here.
When you have a delegate that passes the cell up to your data source/delegate, use the indexPath to grab the next cell (if any) and use the function becomeFirstResponder()on your UITextField to focus it.
Try this code set delegate to textField in Storyboard..
extension LoginPageViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField == userNameTextField {
userNameTextField.resignFirstResponder()
emailTextField.becomeFirstResponder()
} else if textField == emailTextField {
emailTextField.resignFirstResponder()
passwordTextField.becomeFirstResponder()
} else {
performYourAction()
}
return true
}

How To get values of textfields from a UITableViewCell?

So I have thisUITableView cell that has 4 UITextField, and I want to get their values on button click.
This code does not retrieve any values.
#IBAction func printBtnAction(_ sender: Any) {
let cell = self.myTableView.dequeueReusableCell(withIdentifier: "manualAddC1") as! AddFriendC1Cell
let alias = cell.aliasTextField.text!
let primaryPhone = cell.primaryPhoneTextField.text!
let secondaryPhone = cell.seondaryPhoneTextField.text!
let email = cell.emailAddressTextField.text!
print("Alias: \(alias), Phone: \(primaryPhone), Phone2: \(secondaryPhone), Email: \(email)")
}
This is the screenshot of the TableView
I finally figured it out with this simple solution.
#IBAction func saveBtnAction(_ sender: Any) {
let index = IndexPath(row: 0, section: 0)
let cell: AddFriendC1Cell = self.myTableView.cellForRow(at: index) as! AddFriendC1Cell
self.alias = cell.aliasTextField.text!
self.primaryPhone = cell.primaryPhoneTextField.text!
self.secondaryPhone = cell.seondaryPhoneTextField.text!
self.email = cell.emailAddressTextField.text!
print("Alias: \(self.alias), Phone: \(self.primaryPhone), Phone2: \(self.secondaryPhone), Email: \(self.email)")
}
OK. You are dequeueing a tableViewCell when you press on a button.
let cell = self.myTableView.dequeueReusableCell(withIdentifier: "manualAddC1") as! AddFriendC1Cell
I believe that you want to get a reference to an existing tableViewCell like this:
if let cell = tableView.cellForRow(at: indexPath) as? AddFriendC1Cell {
// do what you need with cell
}
Even though this would work, I wouldn't suggest this approach. What if user is using a smaller-screen phone like iPhone 4 and some cells are not visible on the screen? I think that in that case tableView.cellForRow would return nil for non-visible cell.
I would suggest implementing textField:shouldChange in each cell with text field with a delegate to the tableView's viewController. When text is changed in the cell, delegate should propagate the change to the viewController which would save the value in an instance variable.
Then, when you press on the button, you would simply take values from instance variables.
// 1st step
In UITableViewCell
import UIKit
#objc protocol TableViewDelegate: NSObjectProtocol{
func afterClickingReturnInTextField(cell: ThirdTableCell)
}
class TableViewCell: UITableViewCell, UITextFieldDelegate {
#IBOutlet weak var enterTextField: UITextField!
weak var tableViewDelegate: TableViewDelegate?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
enterTextField.delegate = self
}
// #IBAction Of UITextfiled
#IBAction func tapHerre(_ sender: UITextField) {
tableViewDelegate?.responds(to: #selector(TableViewDelegate.afterClickingReturnInTextField(cell:)))
tableViewDelegate?.afterClickingReturnInTextField(cell: self)
}
// UITextField Defaults delegates
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
enterTextField.resignFirstResponder()
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
enterTextField = textField
}
}
// 2nd step
In UITableViewCell
extension ViewController: UITableViewDelegate, UITableViewDataSource, TableViewDelegate {
var valueToPass : String?
func afterClickingReturnInTextField(cell: ThirdTableCell) {
valueToPass = cell.enterTextField.text
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return youArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableview.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell
cell.enterTextField.text = youArray[indexPath.row]
cell.tableViewDelegate = (self as TableViewDelegate)
return cell
}
}
When the keyboard disappears you can find TextField value in valueToPass
I suppose your tableViewCells are not dynamic.
Your cell method will looks like this.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "YourCellID") as! YourClass
cell.yourTextField.tag = indexPath.row
//
// Alias will be tag 0
// Primary Phone will be tag 1
// Secondary Phone will be tag 2
// Email Address will be tag 3, so on and so forth
// Then, attach to each delegate
//
cell.yourTextField.delegate = self
}
Inside your UITableView handling class (which conforms to UITextFieldDelegate protocol), write this.
func textField(_ textField: UITextField, shouldChangeCharactersIn range:NSRange, replacementString string: String) -> Bool {
let kActualText = (textField.text ?? "") + string
switch textField.tag
{
case 0:
aliasValueHolder = kActualText;
case 1:
primaryPhoneValueHolder = kActualText;
case 2:
secondaryPhoneValueHolder = kActualText;
case 3:
emailAddressValueHolder = kActualText;
default:
print("It is nothing");
}
return true;
}
Then you can submit it.
func textField(_ textField: UITextField, shouldChangeCharactersIn range:NSRange, replacementString string: String) -> Bool {
// let kActualText = (textField.text ?? "") + string
var kActualText = (textField.text! as NSString).replacingCharacters(in: range, with: string)
kActualText = kActualText.trimmingCharacters(in: .whitespaces)
if textField.tag == 0
{
email_address = kActualText;
}
else if textField.tag == 3
{
password = kActualText;
}
else
{
print("It is nothing")
}
return true;
}
In my opinion, you should implement TextField delegates methods in the tableCell class and manage all the validations and input text in tableCell class.
Now, you will need to fetch all entered values, for this, you have to use Protocol in tableCell class and send entered value using the delegate to viewController also with the tag to identify that which value has entered like the Phone number or email.
Using this way, your code will be reduced and structured.
Happy Coding !!

Setup inputView for different UITextFields in UITableView

I have UITableView with UITextFields in custom cells.
For UITextField I use custom inputView:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier, forIndexPath: indexPath) as! Item
cell.price.text = ""
cell.price.delegate = self
return cell
}
func textFieldDidBeginEditing(textField: UITextField) {
textField.inputView = keyboardView
itemPrice = textField
}
func numberWasTapped(number: String!) {
itemPrice.insertText(number!)
}
With delegate method:
#IBAction func keyTaped(sender: UIButton) {
switch sender.tag {
case 112:
if !isCommaWasPressed {
isCommaWasPressed = true
sender.enabled = false
self.delegate?.numberWasTapped(sender.titleLabel!.text)
}
break
default:
self.delegate?.numberWasTapped(sender.titleLabel!.text)
}
My custom inputView is the calculator keyboard with the all logic in the Keyboard class: it controls if comma was pressed and how many numbers was entered after the comma.
For example, if comma was pressed, then commaButton.enabled = false in Keyboard class.
I couldn't figure out how to set the commaButton.enabled = true in Keyboard class when I'm switching to another UITextField.
I tried textField.reloadInputViews() in
textFieldDidBeginEditing(_:) method but it doesn't work.
I think, I should get the information from UITextField and pass it to Keyboard's class logic. But I don't know how to do it.
I found the solution.
I moved keyboard logic to main ViewController and no need to pass textField data to Keyboard class.

How to save text field value in uicollectionviewcell

hi i have text field in uicollectionviewcell
so what i need it example :
when i edit text filed value in row 5 and i done it and go to text filed in row 20 to edit value the collectionview has reloaded and forget value in row 5,
so i need way to save value temporarily while do I change it manually
this my code :
cell.foodNumber.tag = indexPath.row
if let foodcodes = self.menu![indexPath.row]["code"] as? NSString {
if contains(self.indexPathsForSelectedCells, indexPath) {
cell.currentSelectionState = true
cell.foodNumber.enabled = true
cell.foodNumber.text = "1"
println("foods:\(foodcodes) Count:\(cell.foodNumber.text)")
println(cell.foodNumber.tag)
} else {
cell.foodNumber.enabled = false
cell.foodNumber.text = nil
}
}
Implement in your ViewController the UITextFieldDelegate protocol, specifically the textField:didEndEditing method.
Save your indexPath.row in the textField.tag as you're doing, and set the delegate to the controller, where you can save the value.
This is a very simplistic example:
class MyViewController : UITableViewController {
var texts = [Int:String]()
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier( "Cell" ) as! UITableViewCell
cell.textField.delegate = self
cell.textField.tag = indexPath.row
// restore saved text, if any
if let previousText = texts[indexPath.row] {
cell.textField.text = previousText
}
else {
cell.textField.text = ""
}
// rest of cell initialization
return cell
}
}
extension MyViewController : UITextFieldDelegate {
func textFieldDidEndEditing(textField: UITextField) {
// save the text in the map using the stored row in the tag field
texts[textField.tag] = textField.text
}
}