Hiding buttons in cells - ios

I am developing app which users will choose one of the two pictures in one cell. My prototype cell looks like :
and I have
cell.rightVoteButton.addTarget(self, action: #selector(voteRightButtonPressed), forControlEvents: .TouchUpInside)
cell.leftVoteButton.addTarget(self, action: #selector(voteLeftButtonPressed), forControlEvents: .TouchUpInside)
in the tableView function.
func voteRightButtonPressed(sender:UIButton){
print("Right Vote clicked is \(sender.tag)")
print(self.polls[sender.tag].poll_id)
}
in this way I am printing the polls id and cells index.
I want to hide the Vote button after clicking specific cell.
For example if I click the vote in first cell and the left picture, I want to hide the two buttons on the first cell. I now the cell's index but how can hide the buttons in specific cell.
My Custom TableViewCell:
class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var leftImage: UIImageView!
#IBOutlet weak var rightImage: UIImageView!
#IBOutlet weak var userPicture: UIImageView!
#IBOutlet weak var userName: UILabel!
#IBOutlet weak var leftButton: UIButton!
#IBOutlet weak var rightButton: UIButton!
#IBOutlet weak var pollDescription: UILabel!
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
}
}

Rather than using tags, which have no intrinsic meaning and are easy to confuse, you can say something like:
func voteRightButtonPressed(sender:UIButton){
let location = self.tableView.convertPoint(sender.bounds.origin, fromView:sender)
let indexPath = self.tableView.indexPathForRowAtPoint(location)
if let cell = self.tableView.cellForRowAtIndexPath(indexPath) as? CustomUITableViewCell {
//hide views in cell and update your model to reflect vote.
}
print("Right Vote clicked is \(indexPath.row)")
print(self.polls[indexPath.row].poll_id)
}
Once you have the cell you can hide the views you want and you can update your model to reflect the vote just cast.

I suppose you have a tableview with several cells of this type, if this is the case you need a custonTableViewCell where you put this code. the buttons respond to a #IBAction that hide the buttons and call a delegate in his UITableViewController.
understand your custonTableViewCell like a viewController for each cell
add this in your custon cell and point the button
// IBAction for buttons
#IBAction func buttonPress(sender: UIButton){
leftButton.hidden = true
rightImage.hidden = true
self.delegate?.buttonPress(sender.tag)
}
add this before your custon cell class definition
protocol CustomTableViewCellDelegate {
func buttonPress(tag: Int)
}
and this after:
var delegate : CustomTableViewCellDelegate?
and in your tableviewcontroller
class TableViewController: UITableViewController, CustomTableViewCellDelegate
and your new func in some place
func buttonPress(tag: Int){
print(tag)
}

Related

Swift how to update a subview's label and imageview using a button in a tableview cell

I want to update a subview's label text and image view photo in my storyboard when I click on a button in my TableCell. I have tried using tableView didSelectRowAt but it only works when I highlight the cell not when I use a the tableviewcell's button.
Here you can see a video of my issue.
https://www.loom.com/share/1f147a67bea548b192b654ceb78722c9
Below here you can see my code used to update the subview using didSelectRowAt
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
EditViewDescriptionLabel.text = userPostDescription[indexPath.row]
EditPostImageView.sd_setImage(with: URL(string: userPostImageArray[indexPath.row]))
}
Is there a way to update my subview by clicking on the gear icon instead?
Below is my FeedViewCell Code
//
// FeedCell.swift
// VidaClock
//
// Created by Irving Gonzalez on 5/30/20.
// Copyright © 2020 Viva La App. All rights reserved.
//
import UIKit
protocol EditPostDelegate {
func gearButtonPressed(_ sender: Any)
}
class FeedCell: UITableViewCell {
#IBOutlet weak var FeedCellUserNameLabel: UILabel!
#IBOutlet weak var userProfilePhotoFeedCellLabel: UIImageView!
#IBOutlet weak var dateFeedCellLabel: UILabel!
#IBOutlet weak var postImageFeedCellLabel: UIImageView!
#IBOutlet weak var likeCountFeedCellLabel: UILabel!
#IBOutlet weak var postDescriptionLabel: UILabel!
#IBOutlet weak var documentIDLabel: UILabel!
#IBOutlet weak var FeedViewGearButtonOutlet: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func layoutSubviews() {
super.layoutSubviews()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
#IBAction func likeButtonClicked(_ sender: Any) {
}
var delegate1: EditPostDelegate?
#IBAction func postGearButtonPressed(_ sender: Any) {
print("postGearButtonPressed")
delegate1?.gearButtonPressed(AnyObject.self)
}
}
You need to set the text for your EditViewDescriptionLabel label once the gear icon is pressed as well. You have a delegate to pass the message over to your viewcontroller. Within the gearButtonPressed call, set the text for your label similar to how you do in didSelectRowAt indexPath.
You need to set the text for your EditViewDescriptionLabel label once the gear icon is pressed as well. You have a delegate to pass the message over to your viewcontroller. Within the gearButtonPressed call, set the text for your label similar to how you do in didSelectRowAt indexPath.
Make your protocol like the below
(Pass data that best fits your needs. Here I am passing the description alone)
protocol EditPostDelegate: class {
func gearButtonPressed(description: String)
}
Then on button action,
if let descriptionContent = postDescriptionLabel.text{
delegate1?.gearButtonPressed(description: descriptionContent)
}
Then set the text for editViewDescriptionLabel in the gearButtonPressed method implementation and then show your view controller.
Pass the data you need to use to your view controller like so.
Also, consider naming your variables in camelCase.

Swift 4.2: Unable to add custom behaviour to a custom UITableViewCell using Protocol oriented delegate concepts

I've a custom UITableViewCell, in that I've two UILabels & one UIButton. I'm able to load data...and display it as per requirement.
Problem Statement-1: Now problem exist in my UIButton, which is in my UICustomTableViewCell. Due to this I'm unable to handle click event on that UIButton.
Problem Statement-2: On button Click I have to identify the index of that Button click and pass data to next ViewController using segue.
Now have a look on...what did I've tried for this...
Yes, first-of-all I have thought that Binding IBOutlet action in my CustomCell will resolve my problem...but actually it doesn't solved my problem.
After that I've accessed button using .tag and initialised index path.row to it.
But it won't helped me.
So now I'm using Protocol oriented concept using delegate to handle click event on my UIButton which is available in CustomCell.
What did I tried:
SwiftyTableViewCellDelegate:
protocol SwiftyTableViewCellDelegate : class {
func btnAuditTrailDidTapButton(_ sender: LeadCustomTableViewCell)
}
CustomTableViewCell with delegate:
class LeadCustomTableViewCell: UITableViewCell {
#IBOutlet weak var lblMeetingPersonName: UILabel!
#IBOutlet weak var lblPolicyNo: UILabel!
#IBOutlet weak var btnLeadAuditTrail: UIButton!
weak var delegate: SwiftyTableViewCellDelegate?
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
#IBAction func btnAuditTrailTapped(_ sender: UIButton) {
delegate?.btnAuditTrailDidTapButton(self)
}
}
ViewController implementing delegate:
class LeadViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, SwiftyTableViewCellDelegate {
//IBOutlet Connections - for UITableView
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
//setting dataSource & delegates of UITableView with this ViewController
self.tableView.dataSource = self
self.tableView.delegate = self
//Reloading tableview with updated data
self.tableView.reloadData()
//Removing extra empty cells from UITableView
self.tableView.tableFooterView = UIView()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:LeadCustomTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "cell") as! LeadCustomTableViewCell
//Assigning respective array to its associated label
cell.lblMeetingPersonName.text = (meetingPersonNameArray[indexPath.section] )
cell.lblPolicyNo.text = (String(policyNoArray[indexPath.section]))
cell.btnLeadAuditTrail.tag = indexPath.section
cell.delegate = self
return cell
}
//This is delegate function to handle buttonClick event
func btnAuditTrailDidTapButton(_ sender: LeadCustomTableViewCell) {
guard let tappedIndexPath = tableView.indexPath(for: sender) else { return }
print("AuditTrailButtonClick", sender, tappedIndexPath)
}
Don't know why this is not working.
Link the touch up inside event in cellForRow by adding the following code:
cell.btnLeadAuditTrail.addTarget(self, action:#selector(btnAuditTrailDidTapButton(_:)), for: .touchUpInside)

make UITableView updates from class of the cells populating it

I have used the same nib file to populated a UITableView. There are 2 different functionalities I have built out for these cells. If you anywhere on the cell other than a small button it runs a function and segues to another page. However if you click the small button, I want to update the UITableView and input a cell below the clicked cell, as a sort of dropdown. I have the below to successfully run a separate functionality:
import UIKit
class ContactCell: UITableViewCell {
//below are the outlets for the conact cells
#IBOutlet weak var msgStatus: UIView!
#IBOutlet weak var contactName: UILabel!
#IBOutlet weak var dropDown: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
msgStatus.layer.cornerRadius = msgStatus.frame.size.width/2
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
#IBAction func dropDown(_ sender: Any) {
print("selected drop down")
}
}
Moving forward I need to be able to get the index of the current cell and perform a UITableView update from the UITableViewCell's class. How would I be able to do this?
You could do this with delegation. Create a delegate protocol for your ContactCell:
protocol ContactCellDelegate {
func pleaseAddDropdown(to: ContactCell)
}
Then set up a delegate parameter for the cell:
var delegate: ContactCellDelegate?
Then subscribe your table view to the ContactCellDelegate protocol (you will have to subclass if you are using a standard UITableView). This means you will need to write an implementation of pleaseAddDropdown() for your table view class. When you dequeue a cell make sure the delegate parameter is assigned to your table view.
Now in your implementation of dropdown() you just need to do something like:
guard let _ = delegate else { return }
delegate!.pleaseAddDropdown(to: self)
Which will send that message up to the table view which can take the appropriate action.
Hope that helps.

UITableViewCell Button is not Clickable IOS Swift

So basically I am trying to do this:
I have a TableView that I load a custom cell (xib) into it. This custom cell has its own corresponding custom class to go with it. The cell loads just fine but the button is not clickable (at all, as in you don't even see any type of indication that the button was clicked at all). I did some googling, tried to set the action in the cell, tried using a delegate to handle the action. I am lost.
Here is the code from the files:
ViewController.swift
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Use your cell's reuse identifier and cast the result
// to your custom table cell class.
let cell = tableView.dequeueReusableCellWithIdentifier("ReserveTableViewCell", forIndexPath: indexPath) as! ReserveTableViewCell
cell.delegate = self
let button = cell.locationButton.viewWithTag(1) as? UIButton
button?.addTarget(self, action: #selector(ReserveTableViewController.loc(_:)), forControlEvents: .TouchUpInside)
cell.pickupDate.text = "Today"
cell.returnDate.text = "Tomorrow"
//cell.locationButton.addTarget(self, action: #selector(loc), forControlEvents: .TouchUpInside)
return cell
}
func loc(sender: UIButton!) {
print("here")
}
CustomCell.swift
import UIKit
protocol ReserveTableViewCellDelegate {
func pickupLocationClick(cell: ReserveTableViewCell)
}
class ReserveTableViewCell : UITableViewCell {
#IBOutlet weak var searchButton: UIButton!
#IBOutlet weak var compactIcon: UIImageView!
#IBOutlet weak var midsizeIcon: UIImageView!
#IBOutlet weak var suvIcon: UIImageView!
#IBOutlet weak var luxuryIcon: UIImageView!
#IBOutlet weak var sportIcon: UIImageView!
#IBOutlet weak var pickupIcon: UIImageView!
#IBOutlet weak var pickupDate: UILabel!
#IBOutlet weak var returnDate: UILabel!
#IBOutlet weak var locationButton: UIButton!
var delegate: ReserveTableViewCellDelegate?
#IBAction func locationButtonAction(sender: AnyObject) {
delegate?.pickupLocationClick(self)
}
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
}
}
Some code is still left from other attempts (which is why the protocol method doesn't match the "loc" that is now defined in the viewcontroller.swift file.
In my TableView in storyboard I have selection turned off, when it is on and you tab on the cell it makes it all look "dim" so to speak.
I have the custom class set in my tableview and the outlets/actions are link in IB.
Anyone?
In my experience, it is possible to add functionality to the button in both the Cell file and in the ViewController file (which holds your TableView as a member)
ViewController.swift
#IBAction func locationButtonAction(sender: AnyObject) {
// Do Some Action Here (Which interacts with data members of View
}
CustomCell.swift
#IBAction func locationButtonAction(sender: AnyObject) {
// Do Another Action (Which interacts with data members of the cell)
}
Both of these functions can be linked to the TouchUpInside of the Cell button using the Storyboard Editor!
Best of luck!
Couple confusing things here...
let button = cell.locationButton.viewWithTag(1) as? UIButton
This means, hey locationButton, look in your subviews to find viewWithTag of 1. Not what you want. Just use
let button = cell.locationButton
Then you need to decide what action you're calling and what class does it live in. If you want the button to call an action in the ViewController class you add a target like:
button.addTarget(self, action: #selector(ViewController.loc(_:)), forControlEvents: .TouchUpInside)
If you want the button to call an action inside the ReserveTableViewController class, which honestly is pretty odd, you need a way to reference that class
button.addTarget(myReferenceToTheReserveTableViewControllerClass, action: #selector(ReserveTableViewController.loc(_:)), forControlEvents: .TouchUpInside)
What you may be actually looking for is for the button to call a method inside the cell class, in which you can then respond as necessary or delegate out to another class, which would then be:
button.addTarget(cell, action: #selector(ReserveTableViewCell.loc(_:)), forControlEvents: .TouchUpInside)
I have set up project just like you did. One thing i noticed in your in ViewController.swift is that you have written following code.
let button = cell.locationButton.viewWithTag(1) as? UIButton //If you will print or debug this button you will see nil
print("Button: \(button)") //prints "Button: nil"
button?.addTarget(self, action: #selector(ReserveTableViewController.loc(_:)), forControlEvents: .TouchUpInside)
Above code is not adding target for your Button. It is adding target for your Buttons subview which has tag value 1. Which is actually nil. Try following code.
cell.locationButton.addTarget(self, action: #selector(ReserveTableViewController.loc(_:)), forControlEvents: .TouchUpInside)(self, action: #selector(clicked), forControlEvents: .TouchUpInside)
Try the following code in your ViewController.swift
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Use your cell's reuse identifier and cast the result
// to your custom table cell class.
let cell = tableView.dequeueReusableCellWithIdentifier("ReserveTableViewCell", forIndexPath: indexPath) as! ReserveTableViewCell
cell.delegate = self
//let button = cell.locationButton.viewWithTag(1) as? UIButton
//button?.addTarget(self, action: #selector(ReserveTableViewController.loc(_:)), forControlEvents: .TouchUpInside)
cell.locationButton.addTarget(self, action: #selector(loc), forControlEvents: .TouchUpInside)
cell.pickupDate.text = "Today"
cell.returnDate.text = "Tomorrow"
return cell
}
func loc(sender: UIButton!) {
print("here")
}

Setting delegate for UITextField produces error

I have a table view with prototype cells and a custom table view cell class. In one of the prototype cells I have a UITextField. I'm trying to dismiss the keyboard when the return key is pressed, to do that I'm using the function textFieldShouldReturn and am trying to set the delegate of my UITextView to self(inputText.delegate = self). Unfortunately, without setting the delegate to self results in nothing happening when return is pressed, and with the inputText.delegate = self line the app crashes with the error fatal error: unexpectedly found nil while unwrapping an Optional value.
Here is my custom table view cell file.
import UIKit
class CustomTableViewCell: UITableViewCell, UITextFieldDelegate {
#IBOutlet weak var inputLabel: UILabel!
#IBOutlet weak var inputText: UITextField!
#IBOutlet weak var labelLabel: UILabel!
#IBOutlet weak var labelDetail: UILabel!
#IBOutlet weak var picker: UIPickerView!
#IBOutlet weak var largeInputText: UITextField!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
inputText.delegate = self
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
print("return button in CustomTableViewCell")
inputText.resignFirstResponder()
return true
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Any help would be greatly appreciated.
There could one of these reasons because of which you are getting this error.
You might not have specified the class of your prototype cell in interface builder. See below
You might not have correctly set the IBOutlet property. Check this in last tab on the side bar shown above after clicking on the label in your prototype cell.
NOTE: Make sure that you have set the custom class for your table view controller or view controller as well.
tryn to call awakeFromNib() from viewDidLoad() ; and then you can select what type of keyboard need for edit : inputTextFile.keyboardType = UIKeyboardType.ASCIICapable/EmailAddress/etc

Resources