Setup inputView for different UITextFields in UITableView - swift

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.

Related

Cell button tableView Swift

I have a tableView with Sections and every section got todoitems that u add.
I'm trying to animate in my picture on the todoItem I click with my cell button delegate function. But I really don't know how to connect to just that one item and make it animate.
What I'm trying to get access to is the same access to a cell like I do in didSelectRow but in this cellButtonFunction, since it's the button in the cell I'm gonna press on and not the whole cell.
The thing I wanna accomplish with pressing the button is like this example:
cellPressed.image.ishidden = false
cellPressed.image.animate()
This cell image have an animated class that works set to it, it's just that I need to hit the specific cell for this
Watched a few YouTube videos and researched but I don't get it to work, so I hope you guys can help me
extension ViewController: FirstTableViewCellDelegate {
func myImageButtonTapped(with index: IndexPath, view: AnimatedCheckmarkView) {
HapticsManager.shared.selectionVibrate()
let todo = self.tableViewCoreData[index.section].sortedItems[index.row - 1]
todo.isMarked = !todo.isMarked
if todo.isMarked == true {
self.tableViewCoreData[index.section].totalMarked += 1
view.animate(withDuration: 1.0, delay: 0.7)
view.isHidden = false
do {
try self.context.save()
}
catch{
//error
}
tableView.reloadData()
} else {
view.isHidden = true
self.tableViewCoreData[index.section].totalMarked -= 1
do {
try self.context.save()
}
catch{
//error
}
tableView.reloadData()
}
Here is the function. Litterly everything in this works except the view.animate() that animates one random view instead
First create delegate to receive action from cell
protocol CellDelegate:AnyObject{
/// pass arguments as per requirement
func cell(buttonDidPressed indexPath: IndexPath)
}
Now in your Cell class create weak reference of delegate
class Cell: UICollectionViewCell{
weak var delegate: CellDelegate? = nil
var indexPath: IndexPath!
/// code
#IBAction func buttonDidPressed(_ sender: UIButton) {
delegate?.cell(buttonDidPressed: indexPath)
}
}
now in ur controller confirm this protocol
extension ViewController: UICollectionViewDelegate,
UICollectionViewDataSource,
CellDelegate{
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// let cell : Cell dequeueReusableCell your cell
cell.delegate = self
cell.indexPath = indexPath
return cell
}
func cell(buttonDidPressed indexPath: IndexPath){
// your task on cell click
}
}
You can also use closures in cell class alternative to protocol

textFieldDidEndEditing is not called in swift

I have a textfield in my tableview cell. When I am entering something and click on the submit button, I want to save the text in a struct to use it in other view controller. But the problem is , when I am clicking the submit button for the first time, my textFieldDidEndEditing function is not calling so I am unable to assign the value to the struct.
My code is-
func textFieldDidEndEditing(_ textField: UITextField)
{
let position: CGPoint = textField.convert(CGPoint.zero, to: self.tableView)
if let indexPath = self.tableView.indexPathForRow(at: position)
{
if let cell: InsuranceInformationTableViewCell = self.tableView.cellForRow(at: indexPath) as? InsuranceInformationTableViewCell{
if textField == cell.policyHolderFullNameTextField{
insuranceModel.policuHolderFullName = textField.text
}
}
}
}
SubmitButtonAction-
#IBAction func SubmitButtonAction(_ sender: UIButton) {
if (insuranceModel.policuHolderFullName == nil) {
showAlert(withTitle: "Data Missing", withMessage: "Policy holder fullName field cannot be empty")
return
}
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(insuranceModel) {
let defaults = UserDefaults.standard
defaults.set(encoded, forKey: "SavedInsuranceInformation")
self.navigationController?.pushViewController(StockAndBillPreviewViewController.instantiateStockAndBillPreviewViewController(), animated: true)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
case TableSection.insuranceType.rawValue:
guard let cell = tableView.dequeueReusableCell(withIdentifier: "InsuranceInformationTableViewCell", for: indexPath) as? InsuranceInformationTableViewCell else {
return UITableViewCell()
}
cell.policyHolderFullNameTextField.delegate = self
}
When I am clicking on the submit button it is showing me the error message.
Here i don't want to use "UITextField, shouldChangeCharactersIn range". Becausei have lots of textfields in my tableview cell as it is a medical form.
How to resolve this issue ? Can anyone help me?
1.one of most common reason this might happen is that you might not be assigning the text view delegate method.
So just add "UITextViewDelegate" as conformance to your table View Cell and then set the delegate in storyboard.
2. if you have done the first method and it is still not working then you can follow the most basic way to get whatever there is in text field when you click your submit button.
at anypoint in your code you can access the text in textfield through "textfield.text",
just create an outlet of your text field and use youroutletname.text in submit button to save in struct.
I am not sure that textFieldDidEndEditing is calling in this case. I use the following approach:
(1) define custom cell with UITextView and make cell delegate for UITextViewDelegate textViewDidChange method
(2) create custom cell delegate protocol to send text changes down to TableViewController
(3) make TableViewController delegate for custom cell and record all changes for UITextView text inside the controller

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

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
}
}

How to change cell editing style with animation

In the Clock app on iOS 10, toggling the cells between editing and the default style comes with a smooth animation transition (as seen in the recording below)
I am trying to replicate this transition for a simple app containing a tableview but I do not know how to implement the animation transition.
My app code for the editing style change is below
ViewController.swift
...
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
//Model array for cell data - omitted population of array for simplicity
var notes = [Note]()
//cell editing style
var cellStyleForEditing: UITableViewCellEditingStyle = .none
//The tableview
#IBOutlet weak var NoteTable: UITableView!
...
#IBAction func enableEdittingBttn(_ sender: AnyObject) {
if(cellStyleForEditing == .none) {
cellStyleForEditing = .delete
self.NoteTable.reloadData()
} else {
cellStyleForEditing = .none
self.NoteTable.reloadData()
}
}
//delegate function sets cell editing style on table load/reload
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return cellStyleForEditing
}
...
//omitted tableview delegate methods
}
As you can see, I achieve the cell style change by reloading the table data after changing the table's cell editing style.
I have omitted all irrelevant code for simplicity.
Instead of reloading your table's data when enabling or disabling editing, call setEditing(_:animated:) with animated true.
if(cellStyleForEditing == .none) {
cellStyleForEditing = .delete
} else {
cellStyleForEditing = .none
}
NoteTable.setEditing(cellStyleForEditing != .none, animated: true)

iOS Swift - UITableViewCell Custom Subclass not displaying content

I have a UITableView that I've created in a UIStoryboard that has two Dynamic Prototype UITableViewCells:
The screenshot will show you that I have the first UITableViewCell's style set to Subtitle, and the second is set to custom with a label "Tap to Add" in the center. The first has an identifier of "Cell" and the second "AddCell". I've set up a UITableViewController (I've also tried a UITableView in a UIViewController), UITableViewCell subclass in Swift and I've connected all of my outlets. However, when I run the simulator the cell is loaded and it is tappable, but I have not been able to get it to display any content. (I've tried adding other controls, but nothing will appear when the cell is loaded. The only thing that I can change is the contentView's backgroundColor.)
I have the following Swift code for the UITableViewController:
import UIKit
class ListTableViewController: UITableViewController {
var listObjects: ListObject[] = DataManager.instance.allListObjects() as ListObject[]
init(style: UITableViewStyle) {
super.init(style: style)
// Custom initialization
}
init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.registerClass(AddListObjectTableViewCell.classForCoder(), forCellReuseIdentifier: "AddCell")
}
#IBAction func editButtonPressed(editButton: UIBarButtonItem) {
if (self.tableView.editing) {
editButton.title = "Edit"
self.tableView.setEditing(false, animated: true)
} else {
editButton.title = "Done"
self.tableView.setEditing(true, animated: true)
}
}
// #pragma mark - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView?) -> Int {
return 1
}
override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int {
return listObjects.count + 1
}
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cellIdentifier = (indexPath.row < listObjects.count) ? "Cell" : "AddCell"
var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as UITableViewCell
if (indexPath.row < listObjects.count) {
let currentListObject : ListObject = listObjects[indexPath.row]
cell.textLabel.text = currentListObject.name
cell.detailTextLabel.text = currentListObject.detail
} else {
cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as AddListObjectTableViewCell
if (cell == nil) {
cell = AddListObjectTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: cellIdentifier)
}
}
return cell
}
override func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
if (indexPath.row < listObjects.count) {
} else {
self.performSegueWithIdentifier("AddListObjectShow", sender: self)
}
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView?, canEditRowAtIndexPath indexPath: NSIndexPath?) -> Bool {
return (indexPath?.row < listObjects.count) ? true : false
}}
I also have the following Swift for my UITableViewCell:
import UIKit
class AddListObjectTableViewCell: UITableViewCell {
#IBOutlet var addLabel : UILabel
init(style: UITableViewCellStyle, reuseIdentifier: String) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
// Initialization code
}
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
}}
Finally, here is a screenshot of the simulator with the empty cell visible when selected:
I've double checked all that all of my outlets are connected, that my class names are set properly in Interface Builder, I've registered the class of my UITableViewCell with the tableView, and everything seems to be configured correctly. Is it possible this is a bug? Any help would be greatly appreciated.
I believe it has to do with the sizing in Storyboard. It seems now it likes to default to a wider view and most people including me (and judging by your storyboard view width, you) prefer having the width set to 'Compact'.
In storyboard either try setting your width/height to any/any or in the inspector for your labels inside the cells scroll all the way down and play the 'Installed' checkbox and you'll notice it has various options for the sizing class. If it's like mine, you'll have the first 'Installed' one unchecked and a second one for your sizing option checked. I removed the custom 'Installed' and checked the default one and then moved my labels into place.
I don't believe I have enough reputation to post more than 1 image or 2 links, wish I could to explain what I mean easier.
I had many hours in finding out, why my sample with the same issue as stated here wasn't working. I'm using story boards and swift 2 (xcode 7.2).
Once I removed
self.tableView.registerClass(AddListObjectTableViewCell.classForCoder(), forCellReuseIdentifier: "AddCell")"
in viewDidLoad() it worked for me. I just used dequeueReusableCellWithIdentifier() as stated in this sample, filled the cell, that was it...
Kind regards,
Michel