I have a stackView(vertical) which contains labels and bottom description label is hidden by default. And I implemented an arrow button at the right side of the cell. By clicking the button, I just want to show the hidden description label and stackView should expand automatically and make cell bigger. This was my basic idea to implement expandable cell.
So this is the code I used to get desired results:
#objc func downArrowButtonClicked(_ sender: UIButton){
let indexPath = IndexPath(row: sender.tag, section: 0)
selectedIndex = indexPath
selectedCellIndex = sender.tag
isDescHidden = !isDescHidden
tableView.reloadRows(at: [indexPath], with: .automatic)
}
Above is the code for the button inside clicked cell. I went with the idea to reload that particular index. I created a variable named selectedCellIndex of in which I use in cellForRowAt method to make some changes.
I also had the implement some code in viewDidLayoutSubviews() as when I first clicked the cell wasn't getting expanded fully. here's that just in case:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let indexPath = selectedIndex
tableView.reloadRows(at: [indexPath ?? IndexPath(row: 0, section: 0)], with: .automatic)
}
And calling it in willDisplay method which finally fixed the cell expansion issue:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
viewDidLayoutSubviews()
}
And here is my cellForRowAt function:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath) as! CustomTableViewCell
if indexPath.row == 0 {
cell.lblTitle.text = "Title 1"
cell.lblDesc.text = "Desc 1"
}
else if indexPath.row == 1 {
cell.lblTitle.text = "Title 2"
cell.lblDesc.text = "Desc 2"
}
else {
cell.lblTitle.text = "Title 3"
cell.lblDesc.text = "Desc 3"
}
if selectedCellIndex != nil {
if isDescHidden == false {
if cell.isDescHidden == true {
cell.lblDesc.isHidden = false
cell.btnArrow.setImage(UIImage(systemName: "chevron.up"), for: .normal)
}
else {
cell.lblDesc.isHidden = true
cell.btnArrow.setImage(UIImage(systemName: "chevron.down"), for: .normal)
}
}
else {
if cell.isDescHidden == true {
cell.lblDesc.isHidden = true
cell.btnArrow.setImage(UIImage(systemName: "chevron.down"), for: .normal)
}
else {
cell.lblDesc.isHidden = false
cell.btnArrow.setImage(UIImage(systemName: "chevron.up"), for: .normal)
}
}
cell.isDescHidden = !cell.isDescHidden
}
cell.btnArrow.tag = indexPath.row
cell.btnArrow.addTarget(self, action: #selector(downArrowButtonClicked(_:)), for: .touchUpInside)
return cell
}
This approach gets too confusing as you can see from the above code. The isDescHidden variable is defined in both Main view controller as well as table view cell class and I was trying to use both to expand or collapse a particular cell. However first time it works but if I have 3 cells expanded, collapsing button click doesn't work for 1-2 clicks then works.
Is there a better approach for this kind of problem? Or is there any way I can directly set cell.isDescHidden value from #objc func downArrowButtonClicked(_ sender: UIButton) function? So I can use that in cellForRowAt function?
I would be glad if I could directly make changes to cell variables from that.
Use the following function for automatic height for rows and provided top and bottom constraints to your stackView
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
Here is my CustomCell
class CustomCell: UITableViewCell {
#IBOutlet weak var titleCell: UILabel!
#IBOutlet weak var detail: UILabel!
#IBOutlet weak var arrowButton: UIButton!
let upArrow = UIImage(systemName: "chevron.up.circle.fill")
let downArrow = UIImage(systemName: "chevron.down.circle.fill")
var onArrowClick: ((UIButton)->())!
#IBAction func handleArrowButton(sender: UIButton){
onArrowClick(sender)
}
func updateArrowImage(expandStatus: Bool){
arrowButton.setImage(expandStatus ? downArrow : upArrow, for: .normal)
}
}
For sample Data
let data = [
["Nothing", "description is very long description is very long description is very long description is very "],
["Nothing", "description is very long "],
["Nothing", "description is very long "],
["Nothing", "description is very long "],
["Nothing", "description is very long "]
]
var eachCellStatus: [Bool] = []
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
for _ in data {
eachCellStatus.append(true)
}
}
TableView methods are like this
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CustomCell
cell.titleCell.text = data[indexPath.row][0]
cell.detail.text = data[indexPath.row][1]
cell.detail.isHidden = eachCellStatus[indexPath.row]
cell.updateArrowImage(expandStatus: self.eachCellStatus[indexPath.row])
cell.onArrowClick = { button in
self.eachCellStatus[indexPath.row].toggle()
cell.updateArrowImage(expandStatus: self.eachCellStatus[indexPath.row])
tableView.reloadRows(at: [indexPath], with: .automatic)
}
return cell
}
First create a model to show data into cell. You have to preserve the state of cell.
struct CellData {
var title: String
var details: String
var isExpanded: Bool
}
In CustomTableViewCell add a property for cellData and assign Outlets data from it. Also create a protocol to reload row from UIViewController
protocol CustomTableViewCellDelegate {
func reloadRow(sender: CustomTableViewCell, flag: Bool)
}
class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var detailsLabel: UILabel!
#IBOutlet weak var showButton: UIButton!
var indexPath: IndexPath?
var delegate: CustomTableViewCellDelegate?
var data: CellData? {
didSet {
if let data = data {
if data.isExpanded == false {
detailsLabel.isHidden = true
showButton.setImage(UIImage(systemName: "chevron.down"), for: .normal)
}else {
detailsLabel.isHidden = true
showButton.setImage(UIImage(systemName: "chevron.up"), for: .normal)
}
titleLabel.text = data.title
detailsLabel.text = data.details
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
titleLabel.text = nil
detailsLabel.text = nil
}
#IBAction func showButtonAction(_ sender: UIButton) {
if var data = data {
data.isExpanded.toggle()
delegate?.reloadRow(cell: self, flag: data.isExpanded)
}
}
}
In UIViewController add an array of CellData type. You may assign it's data in viewDidLoad() method.
var tableData: [CellData]
Modify numberOfRowsInSection() and cellForRow() method like bleow.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath) as! CustomTableViewCell
cell.data = tableData[indexPath.row]
cell.delegate = self
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
Then confirm CustomTableViewCellDelegate protocol to UIViewController
extension ViewController: CustomTableViewCellDelegate {
func reloadRow(sender: CustomTableViewCell, isExpanded: Bool) {
guard let tappedIndexPath = tableView.indexPath(for: sender) else { return }
tableData[tappedIndexPath.row].isExpanded = isExpanded
tableView.reloadRows(at: [indexPath], with: UITableView.RowAnimation.automatic)
}
}
Related
I am trying to add an action to my "like" button. So that when the user taps the heart UIButton in a cell, the heart in the cell they tapped updates to a pink heart showing that they liked it. But instead it likes the heart they tapped and another random heart in a different cell that they did not interact with. I have been on this all day and any help would be grateful. For Example, if I like/tap my heart UIButton the buttons image I tapped updates, but when I scroll down another random heart updates from that same first cell button tap.
Also When I scroll and the cell leaves view and scroll back up the image returns back to unlike and other like buttons become liked.
Keep a data model for your buttons state
Try with the below code
struct TableModel {
var isLiked: Bool
}
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var dataSource: [TableModel] = []
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
overrideUserInterfaceStyle = .light
dataSource = Array(repeating: TableModel(isLiked: false), count: 20)
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.showsVerticalScrollIndicator = false
self.tableView.reloadData()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
dataSource.count
}
#objc func buttonSelected(_ sender: UIButton) {
dataSource[sender.tag].isLiked = !dataSource[sender.tag].isLiked
let indexPath = IndexPath(row: sender.tag, section: 0)
tableView.reloadRows(at: [indexPath], with: .automatic)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
cell.likeBtn.tag = indexPath.row
cell.likeBtn.addTarget(self, action: #selector(buttonSelected(_:)), for: .touchUpInside)
let isLiked = dataSource[indexPath.row].isLiked
if isLiked {
cell.likeBtn.setImage(UIImage(named: "liked"), for: UIControl.State.normal)
} else {
//set unlike image
}
return cell
}
}
Currently, you have a hardcoded number of rows, but anyway you will need to have a data source with data models. When you press the button, you have to save the state of the button of a specific row. I would recommend you create a model first.
Here I provided an easy (but flexible enough) way how to do this. I haven't debugged it, but it should work and you can see the idea. I hope this would be helpful.
Create Cell Model
struct CellViewModel {
let title: String
var isLiked: Bool
// Add other properties you need for the cell, image, etc.
}
Update cell class
It's better to handle top action right in the cell class. To handle this action on the controller you can closure or delegate like I did.
// Create a delegate protocol
protocol TableViewCellDelegate: AnyObject {
func didSelectLikeButton(isLiked: Bool, forCell cell: TableViewCell)
}
class TableViewCell: UITableViewCell {
// add a delegate property
weak var delegate: TableViewCellDelegate?
#IBOutlet var titleTxt: UILabel!
#IBOutlet var likeBtn: UIButton!
//...
override func awakeFromNib() {
super.awakeFromNib()
// You can add target here or an action in the Storyboard/Xib
likeBtn.addTarget(self, action: #selector(likeButtonSelected), for: .touchUpInside)
}
/// Method to update state of the cell
func update(with model: CellViewModel) {
titleTxt.text = model.title
likeBtn.isSelected = model.isLiked
// To use `isSelected` you need to set different images for normal state and for selected state
}
#objc private func likeButtonSelected(_ sender: UIButton) {
sender.isSelected.toggle()
delegate?.didSelectLikeButton(isLiked: sender.isSelected, forCell: self)
}
}
Add an array of models and use it
This is an updated class of ViewController with usage of models.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
// Provide a list of all models (cells)
private var cellModels: [CellViewModel] = [
CellViewModel(title: "Title 1", isLiked: false),
CellViewModel(title: "Title 2", isLiked: true),
CellViewModel(title: "Title 3", isLiked: false)
]
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
overrideUserInterfaceStyle = .light
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.showsVerticalScrollIndicator = false
self.tableView.reloadData()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// return count of cell models
return cellModels.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
let model = cellModels[indexPath.row]
// call a single method to update the cell UI
cell.update(with: model)
// and you need to set delegate in order to handle the like button selection
cell.delegate = self
return cell
}
}
extension ViewController: TableViewCellDelegate {
func didSelectLikeButton(isLiked: Bool, forCell cell: TableViewCell) {
// get an indexPath of the cell which call this method
guard let indexPath = tableView.indexPath(for: cell) else {
return
}
// get the model by row
var model = cellModels[indexPath.row]
// save the updated state of the button into the cell model
model.isLiked = isLiked
// and set the model back to the array, since we use struct
cellModels[indexPath.row] = model
}
}
I try to use standard selection in isEditing mode. When I press the first time it's selected, but when I press the second time it stays selected visually. If I change isEditing to false and next time set it true I can't select rows which were selected previously but they don't mark.
How to fix it? isEditing change by button.
enter image description here
'''
class PermanentInternalViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate, UIGestureRecognizerDelegate {
var index = 0
var test = ["dghffhfh",
"sadasdsa",
"sgfhghgfh"
]
var selectedArray: [IndexPath] = []
#IBOutlet weak var tableViewInternal: UITableView!
#IBOutlet weak var createButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(tableTapped))
self.tableViewInternal.addGestureRecognizer(tap)
self.tableViewInternal.delegate = self
self.tableViewInternal.dataSource = self
self.tableViewInternal.tableFooterView = UIView()
self.tableViewInternal.allowsMultipleSelectionDuringEditing = true
createButton.layer.cornerRadius = 10
if tableViewInternal.isEditing {
createButton.titleLabel!.text = "Add to your Temporary List"
} else {
createButton.titleLabel!.text = "Create Temporary List"
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
test.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "permanentInsideCell1", for: indexPath) as! customCell
cell.tf.delegate = self
// cell.selectionStyle = .none
cell.tf.text = test[indexPath.row]
cell.tf.isUserInteractionEnabled = false
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! customCell
cell.tf.isUserInteractionEnabled = true
cell.selectionStyle = .none
cell.tf.becomeFirstResponder()
index = indexPath.row
if tableViewInternal.isEditing{
cell.tf.isUserInteractionEnabled = false
}
print (cell.isSelected)
if selectedArray.contains(indexPath) {
// it was already selected
selectedArray.remove(at: selectedArray.firstIndex(of: indexPath)!)
print(selectedArray)
} else {
// wasn't yet selected, so let's remember it
selectedArray.append(indexPath)
print(selectedArray)
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
print("Deselect")
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
test.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
test[index] = textField.text!
tableViewInternal.reloadData()
// textField.resignFirstResponder()
}
#IBAction func createTempList(_ sender: UIButton) {
tableViewInternal.isEditing = true
createButton.setTitle("Add to your Temporary List", for: .normal)
}
func addAction() {
// create a new row by appending new empty strings
test.append("")
tableViewInternal.reloadData()
}
#objc func tableTapped(tap:UITapGestureRecognizer) {
tap.cancelsTouchesInView = false
let location = tap.location(in: self.tableViewInternal)
let path = self.tableViewInternal.indexPathForRow(at: location)
if let _ = path {
// self.tableView(self.tableViewInternal, didSelectRowAt: indexPathForRow)
} else {
// handle tap on empty space below existing rows however you want
if self.tableViewInternal.isEditing {
self.tableViewInternal.isEditing = false
self.createButton.setTitle("Create Temporary List", for: .normal)
} else {
addAction()
}
}
}
}
'''
Solved.
Problem was in cell.selectionStyle = .none
If remove it and use a clear background color for tableview all is working.
I create a custom cell that include tableview
Here's the MainTableView and data
var data = [People(name:"Kevin",age:"18",tall:"180")]
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MainCell", for: indexPath) as! MainTableViewCell
cell.title = data[indexPath.row].name
cell.detail = ["age \(data[indexPath.row].age)","tall \(data[indexPath.row].tall)"]
cell.isExtend = false
return cell
}
I try to tap cell to expand tableView height and load data
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "MainCell", for: indexPath) as! MainTableViewCell
cell.isExpand = !cell.isExpand
}
Here's the MainTableViewCell
class MainTableViewCell: UITableViewCell {
#IBOutlet weak var title: UILabel!
#IBOutlet weak var detailTableView: UITableView!
#IBOutlet weak var detailTableViewHeight: NSLayoutConstraint!
var detail:[String] = []{
didSet{
detailTableView.reloadData()
}
}
var isExpand: Bool = false{
didSet{
detailTableView.isHidden = !isExpand
detailTableView.reloadData()
detailTableViewHeight.constant = isExpand ? detailTableView.contentSize.height:0
}
}
override func awakeFromNib() {
super.awakeFromNib()
detailTableView.delegate = self
detailTableView.dataSource = self
detailTableView.isScrollEnabled = false
detailTableViewHeight.constant = 0
}
}
I use tableView to load data and hide some of theme first, and tapped to show and hide theme
but It happened nothing
Did I forgot something?
In cellforRowAt:
let cell: MoreUserDetails = tableView.dequeueReusableCell(withIdentifier: "MoreUserDetails") as! MoreUserDetails
cell.backgroundColor = .clear
cell.selectionStyle = .none
if isExpand {
// your func when its expanded
}
else {
// your func when its hidden
}
return cell
in did select
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
if isSelected[indexPath.row] {
isExpand[indexPath.row] = false
}
else {
isExpand[indexPath.row] = true
}
self.tableVIew.reloadData()
}
I have a textField, which when touch displays a tableView with some rows.
I'm trying to do this: when a user selects one of the rows, the value of row is placed in the textField and the tableView is closed.
The first part works well for me. The user touch on one row and the textField shows the value of that row. But if I want to close the tableview, I have to press twice on the row.
This is my code:
class Redactar_mensaje: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate {
var values = ["123 Main Street", "789 King Street", "456 Queen Street", "99 Apple Street", "red", "orange", "yellow", "green", "blue", "purple", "owaldo", "ostras", "Apple", "Pineapple", "Orange", "Adidas"]
#IBOutlet weak var campo_para: UITextField!
#IBOutlet weak var tableView: UITableView!
var originalCountriesList:[String] = Array()
override func viewDidLoad() {
super.viewDidLoad()
tableView.isHidden = true
for country in values {
originalCountriesList.append(country)
}
campo_para.delegate = self
tableView.delegate = self
tableView.dataSource = self
campo_para.addTarget(self, action: #selector(textFieldActive), for: UIControlEvents.touchDown)
campo_para.addTarget(self, action: #selector(searchRecords(_ :)), for: .editingChanged)
}
#objc func searchRecords(_ textField: UITextField) {
self.values.removeAll()
if textField.text?.count != 0 {
for country in originalCountriesList {
if let countryToSearch = textField.text{
let range = country.lowercased().range(of: countryToSearch, options: .caseInsensitive, range: nil, locale: nil)
if range != nil {
self.values.append(country)
}
}
}
} else {
for country in originalCountriesList {
values.append(country)
}
}
tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return values.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cellx")
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "cellx")
}
cell?.textLabel?.text = values[indexPath.row]
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
campo_para.text = values[indexPath.row]
tableView.isHidden = true //I need press twice for this. I want press only one
}
func textFieldActive() {
tableView.isHidden = false
}
}
Ideally, the user touches the textField, displays the tableView, chooses one of the values, and it close automatically the tableView. But this last one does not work well.
Any advice?
Details
xCode 8.3, Swift 3.1
Example to Detect Double tap and Single tap on TableViewCell
ViewController.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.tableFooterView = UIView()
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell
cell.label.text = "\(indexPath)"
cell.delegate = self
return cell
}
}
extension ViewController:TableViewCellDelegate {
func tableViewCell(singleTapActionDelegatedFrom cell: TableViewCell) {
let indexPath = tableView.indexPath(for: cell)
print("singleTap \(String(describing: indexPath)) ")
}
func tableViewCell(doubleTapActionDelegatedFrom cell: TableViewCell) {
let indexPath = tableView.indexPath(for: cell)
print("doubleTap \(String(describing: indexPath)) ")
//You can hide your textfield here
}
}
TableViewCell.swift
import UIKit
class TableViewCell: UITableViewCell {
#IBOutlet weak var label: UILabel!
private var tapCounter = 0
var delegate: TableViewCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
let tap = UITapGestureRecognizer(target: self, action: #selector(tapAction))
addGestureRecognizer(tap)
}
func tapAction() {
if tapCounter == 0 {
DispatchQueue.global(qos: .background).async {
usleep(250000)
if self.tapCounter > 1 {
self.doubleTapAction()
} else {
self.singleTapAction()
}
self.tapCounter = 0
}
}
tapCounter += 1
}
func singleTapAction() {
delegate?.tableViewCell(singleTapActionDelegatedFrom: self)
}
func doubleTapAction() {
delegate?.tableViewCell(doubleTapActionDelegatedFrom: self)
}
}
TableViewCellDelegate.swift
import UIKit
protocol TableViewCellDelegate {
func tableViewCell(singleTapActionDelegatedFrom cell: TableViewCell)
func tableViewCell(doubleTapActionDelegatedFrom cell: TableViewCell)
}
Result
Here I put my solution, in case someone else would happen something similar.
Just change the order of the lines and add one more line. First it makes it invisible and then puts the result in the textField and, magically, it worked!
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.isHidden = true
campo_para.text = NombreUsuario[indexPath.row]
campo_asunto.becomeFirstResponder()
}
Thanks!
I Have TableView with the two label and one UIButton inside the Tableview. So on DidSelect method i want to change the UIButton Image of that particular cell. As attach image.
Check This
import UIKit
class ButtonTblViewController: UIViewController,UITableViewDelegate, UITableViewDataSource {
var arry = ["Montitanki Chowk","Greenland Chokdi"]
var SelectData = [NSMutableDictionary]()
#IBOutlet weak var tbleVw: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
for i in 0..<arry.count
{
self.SelectData.append(["data":arry[i],"isSelect":"NO"])
}
self.tbleVw.reloadData()
// Do any additional setup after loading the view.
}
// MARK - tableView Delegates
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return SelectData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:listTble = tableView.dequeueReusableCell(withIdentifier: "CellID", for: indexPath as IndexPath) as! listTble
cell.lblTit.text = self.SelectData[indexPath.row].value(forKey: "data") as? String
cell.btnRdo.tag = indexPath.row
let tapgesture = UITapGestureRecognizer(target: self , action: #selector(self.sectionTapped(_:)))
cell.btnRdo.addGestureRecognizer(tapgesture)
let selData = self.SelectData[indexPath.row].value(forKey: "isSelect") as! NSString
if selData == "NO" {
cell.btnRdo.setImage( UIImage(named: "btnUnSel"), for: .normal)
} else {
cell.btnRdo.setImage( UIImage(named: "btnSel"), for: .normal)
}
return cell
}
#objc func sectionTapped(_ sender: UITapGestureRecognizer){
if(self.SelectData[(sender.view?.tag)!].value(forKey: "isSelect") as! String == "NO"){
self.SelectData[(sender.view?.tag)!].setValue("YES", forKey: "isSelect")
}else{
self.SelectData[(sender.view?.tag)!].setValue("NO", forKey: "isSelect")
}
self.tbleVw.reloadData()
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
class listTble: UITableViewCell {
#IBOutlet weak var lblTit: UILabel!
#IBOutlet weak var btnRdo: UIButton!
}
Out Put
you need to first set button tag in cellForRow method
after in didSelectRowAtIndexPath method you need to set image of button and in didDeselectRowAtIndexPath set unselect image in button.
you can set button image by using :
playButton.setImage(UIImage(named: "play.png"), forState:UIControlState.Normal)
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let btn = (tableView.cellForItem(at: indexPath) as! yourCellName).button else {
return
}
btn.setImage(UIImage(named: "yourSelectedImage name"), for: .normal)
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
guard let btn = (tableView.cellForItem(at: indexPath) as! yourCellName).button else {
return
}
btn.setImage(UIImage(named: "yourNotSelectedImagename"), for: .normal)
}