Want accessory checkmark to show only when tapped on the right - ios

I have a TableView with cells that when pressed anywhere in the cell, it adds a checkmark on the right. I only want the checkmark to show up if the cell is tapped on the right side. Here's the pertinent section of code from the TableViewController:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TaskCell", for: indexPath) as! TaskCell
let task = tasks[indexPath.row]
cell.task = task
if task.completed {
cell.accessoryType = UITableViewCellAccessoryType.checkmark;
} else {
cell.accessoryType = UITableViewCellAccessoryType.none;
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
var tappedItem = tasks[indexPath.row] as Task
tappedItem.completed = !tappedItem.completed
tasks[indexPath.row] = tappedItem
tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.none)
}
}
Is there a simple way to do that, or to do it using storyboard? My Swift skills leave a LOT to be desired. Any help would be appreciated! Thank you!

Instead of the built-in checkmark accessory type, why not provide, as accessory view, an actual button that the user can tap and that can display the checkmark? The button might, for example, display as an empty circle normally and as a circle with a checkmark in it when the user taps it.
Otherwise, you're expecting the user to guess at an obscure interface, whereas, this way, it's perfectly obvious that you tap here to mark the task as done.
Example:
To accomplish that, I created a button subclass and set the accessoryView of each cell to an instance of it:
class CheckButton : UIButton {
convenience init() {
self.init(frame:CGRect.init(x: 0, y: 0, width: 20, height: 20))
self.layer.borderWidth = 2
self.layer.cornerRadius = 10
self.titleLabel?.font = UIFont(name:"Georgia", size:10)
self.setTitleColor(.black, for: .normal)
self.check(false)
}
func check(_ yn:Bool) {
self.setTitle(yn ? "✔" : "", for: .normal)
}
override init(frame:CGRect) {
super.init(frame:frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
The title of the button can be the empty string or a checkmark character, thus giving the effect you see when the button is tapped. This code comes from cellForRowAt::
if cell.accessoryView == nil {
let cb = CheckButton()
cb.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
cell.accessoryView = cb
}
let cb = cell.accessoryView as! CheckButton
cb.check(self.rowChecked[indexPath.row])
(where rowChecked is an array of Bool).

You will have to define your own accessory button, and handle its own clicks.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TaskCell", for: indexPath) as! TaskCell
let task = tasks[indexPath.row]
cell.task = task
let checkButton = UIButtonSubclass()
...configure button with your circle and check images and a 'selected property'...
checkButton.addTarget(self, action:#selector(buttonTapped(_:forEvent:)), for: .touchUpInside)
cell.accessoryView = checkButton
checkButton.selected = task.completed //... this should toggle its state...
return cell
}
func buttonTapped(_ target:UIButton, forEvent event: UIEvent) {
guard let touch = event.allTouches?.first else { return }
let point = touch.location(in: self.tableview)
let indexPath = self.tableview.indexPathForRow(at: point)
if let task = tasks[indexPath.row] {
task.completed = !task.completed
}
tableView.reloadData() //could also just reload the row you tapped
}
Though, it has been noted that using tags to detect which row was tapped is dangerous if you start to delete rows. You can read more here https://stackoverflow.com/a/9274863/1189470
EDITTED
Removed the reference to tags per #matt

Related

UISwitch is not invoking the function when added with tableView cell

I have added a switch along with each cell in table view but the switch function is not get called. If I give the switch in the front page its displaying successfully. But in tableview cell its not working `
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = models[indexPath.row].Address
cell.textLabel?.text = models[indexPath.row].Number
cell.textLabel?.text = models[indexPath.row].Role
cell.textLabel?.text = models[indexPath.row].Name
//switch
let mySwitch = UISwitch(frame: .zero)
mySwitch.setOn(false, animated: true)
mySwitch.tag = indexPath.row
mySwitch.tintColor = UIColor.red
mySwitch.onTintColor = UIColor.green
mySwitch.addTarget(self, action: #selector(switchValueDidChange(_:)), for: .valueChanged)
cell.accessoryView = mySwitch
return cell
}
#IBAction func switchValueDidChange(_sender: UISwitch){
if _sender .isOn{
print("switch on")
view.backgroundColor = UIColor.red }
else{
view.backgroundColor = UIColor.systemPurple
}
}
`
The signature is wrong. There must be a space character between the underscore and sender. And if it's not a real IBAction replace #IBAction with #objc
#objc func switchValueDidChange(_ sender: UISwitch) {
if sender.isOn {...
and – not related to the issue – the selector can be simply written
#selector(switchValueDidChange)

Table View Data is overridden

I have a UITableView. Its cell contains a label that will display a question, a yes button and a no button. The goal is to view questions one by one.
First I call the API to get the questions in the viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
tableView.allowsSelection = false
getQuestions(baseComplainID: "1") { (questions, error) in
self.questions = questions
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
In the cellForRowAt method I display them one by one:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? TableViewCell else {
fatalError("Fatal Error")
}
cell.yesButton.isHidden = false
cell.noButton.isHidden = false
if indexPath.row + 1 == displayNumber {
cell.questionLabel.text = questions[indexPath.row].question_name
} else {
cell.yesButton.isHidden = true
cell.noButton.isHidden = true
}
cell.yesButton.addTarget(self, action: #selector(action), for: .touchUpInside)
cell.noButton.addTarget(self, action: #selector(action), for: .touchUpInside)
return cell
}
and this is the action being executed on clicking yes or no:
#objc func action(sender: UIButton){
let indexPath = self.tableView.indexPathForRow(at: sender.convert(CGPoint.zero, to: self.tableView))
let cell = tableView.cellForRow(at: indexPath!) as? TableViewCell
cell?.yesButton.isEnabled = false
cell?.noButton.isEnabled = false
if sender == cell?.yesButton {
sender.setTitleColor(.black, for: .normal)
sender.backgroundColor = .green
} else {
sender.setTitleColor(.black, for: .normal)
sender.backgroundColor = .green
}
displayNumber += 1
self.tableView.reloadData()
}
Here I just change the background color of the button and increment the display number to display the next question.
All of this works perfect EXCEPT when I scroll, the data gets overridden and sometimes I find the question label empty and the questions replaces each other. I know this is normal due to the cell reusability but I don't know how to fix it.
Any suggestions please?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? TableViewCell else {
fatalError("Fatal Error")
}
cell.yesButton.isHidden = false
cell.noButton.isHidden = false
if indexPath.row + 1 == displayNumber {
cell.questionLabel.text = questions[indexPath.row].question_name
} else {
cell.yesButton.isHidden = true
cell.noButton.isHidden = true
}
cell.yesButton.addTarget(self, action: #selector(action), for: .touchUpInside)
cell.noButton.addTarget(self, action: #selector(action), for: .touchUpInside)
return cell
}
i feel like your issue lies here in cellForRowAt function.
you have this written
if indexPath.row + 1 == displayNumber { your code here }
but i am unsure as to why you need this.
you should be doing something like this inside cellForRowAt
let data = self.questions
data = data[indexPath.row]
cell.questionLabel.text = data.question_name
you should not be adding 1 to your indexPath.row
You're going to need to keep track of your yes's no's and neither's for each cell. I'd tack an enum onto another data structure along with your questions. Your primary problem was that you were only keeping track of your question. You need to keep track of your answer as well. That way, when you load a cell, you can configure each button with the colors that you want in cellForRow(at:)
struct QuestionAndAnswer {
enum Answer {
case yes
case no
case nada
}
var question: Question
var answer: Answer
}
And try not to reload your whole tableView when a button is pressed. tableView.reloadData() is expensive and distracting to the user. You should only be reloading the row that changed when a button was pressed.
Add callbacks on your cell so that you know which cell the corresponding buttons belong to. Notice how in the onYes and onNo callbacks we keep track of your "yes" or "no" selection then immediately reload the row below. When the row is reloaded, we finally know which color to make the button.
class AnswerCell: UITableViewCell {
#IBOutlet weak var yesButton: UIButton!
#IBOutlet weak var noButton: UIButton!
var onYes: (() -> Void)) = {}
var onNo: (() -> Void)) = {}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// ...
cell.yesButton.backgroundColor = qAndA.answer == .yes ? .green : .white
cell.noButton.backgroundColor = qAndA.answer == .no ? .green : .white
cell.onYes = {
questionsAndAnswers[indexPath.row].answer = .yes
tableView.reloadRows(at: [indexPath], with: .fade)
}
cell.onNo = {
questionsAndAnswers[indexPath.row].answer = .no
tableView.reloadRows(at: [indexPath], with: .fade)
}
// ...
}
Well, assume you have 10 questions, so a very simple and workaround fix is to declare a new array which has 10 elements as follow
var questionIsLoaded = Array(repeating:true , count 10)
the previous line will declare an array with 10 elements each element is bool which in our case will be true
then declare a function that handles if the question is loaded or not as follows, so if the question is loaded thus, the question with its indexPath should be marked as true and as a result, the yes and no buttons should be hidden else, the buttons should be shown
func handleQuestionIfLoaded(cell:yourCellType, indexPath:IndexPath) {
if questionIsLoaded[indexPath.row] , indexPath.row + 1 == displayNumber { {
questionIsLoaded[indexPath.row] = false
cell.questionLabel.text = questions[indexPath.row].question_name
cell.yesButton.isHidden = questionIsLoaded[indexPath.row]
cell.noButton.isHidden = questionIsLoaded[indexPath.row]
} else {
cell.yesButton.isHidden = questionIsLoaded[indexPath.row]
cell.noButton.isHidden = questionIsLoaded[indexPath.row]
}
cell.yesButton.addTarget(self, action: #selector(action), for: .touchUpInside)
cell.noButton.addTarget(self, action: #selector(action), for: .touchUpInside)
}
then replace the body of cellForRowAt with the function above, then your action function will be as follows
#objc func action(sender: UIButton){
let indexPath = self.tableView.indexPathForRow(at: sender.convert(CGPoint.zero, to: self.tableView))
let cell = tableView.cellForRow(at: indexPath!) as? TableViewCell
cell?.yesButton.isEnabled = questionIsLoaded[indexPath.row]
cell?.noButton.isEnabled = questionIsLoaded[indexPath.row]
if sender == cell?.yesButton {
sender.setTitleColor(.black, for: .normal)
sender.backgroundColor = .green
} else {
sender.setTitleColor(.black, for: .normal)
sender.backgroundColor = .green
}
displayNumber += 1
self.tableView.reloadData()
}
Now, your cells depend on an external dependency which is the array you have declared earlier, this means that when the cells are dequeued, they will be reused according to if the question is loaded or not by asking the array's element at the specific indexPath at first if the element is true or false

Table View Cell getting deselected after first tap.

Gif depicting that :
When user selecting table view cell for first time(checkbox ticked first time) , cell getting selected but after that it is deselected automatically and nothing happens when i am tapping second time.
But when i am tapping third time cell getting selected properly and on 4th tap it is deselecting properly and so on for 5th , 6th time onwards.
My didSelectRowAt() method looks like this :
func expandableTableView(_ expandableTableView: LUExpandableTableView, didSelectRowAt indexPath: IndexPath) {
let cell = expandableTableView.cellForRow(at: indexPath) as! FilterTableCell
let dictKey : String = FilterKeysMapping[FilterKeysFront.object(at: indexPath.section) as! String]!
if(self.FilterDictAPI[dictKey] == nil){
self.FilterDictAPI[dictKey] = [indexPath.row: self.FilterValueArray.object(at: indexPath.row)]
}
else{
self.FilterDictAPI[dictKey]![indexPath.row] = self.FilterValueArray.object(at: indexPath.row)
}
self.expandableTableView.beginUpdates()
cell.button.isSelected = true
self.expandableTableView.reloadRows(at: [indexPath], with: .automatic)
self.expandableTableView.endUpdates()
expandableTableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
}
didDeselectRowAt() method is like this :
func expandableTableView(_ expandableTableView: LUExpandableTableView, didDeselectRowAt indexPath: IndexPath) {
print("Did Deselect Cell at section \(indexPath.section) row \(indexPath.row)")
let cell = expandableTableView.cellForRow(at: indexPath) as! FilterTableCell
cell.button.isSelected = false
let dictKey : String = FilterKeysMapping[FilterKeysFront.object(at: indexPath.section) as! String]!
if(self.FilterDictAPI[dictKey] != nil){
self.FilterDictAPI[dictKey]?.removeValue(forKey: indexPath.row)
}
print("dict after removing values : \(self.FilterDictAPI)")
}
cellForRowAt() method is :
func expandableTableView(_ expandableTableView: LUExpandableTableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = expandableTableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as? FilterTableCell else {
assertionFailure("Cell shouldn't be nil")
return UITableViewCell()
}
cell.selectionStyle = UITableViewCellSelectionStyle.none
cell.label.text = "\(self.FilterValueArray.object(at: indexPath.row))" + " (" + "\(self.FilterCountArray.object(at: indexPath.row))" + ")"
return cell
}
Table View Cell is :
class FilterTableCell: UITableViewCell {
let label = UILabel()
let button = UIButton()
var check = Bool()
// MARK: - Init
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(label)
contentView.addSubview(button)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Base Class Overrides
override func layoutSubviews() {
super.layoutSubviews()
label.frame = CGRect(x: 42, y: 0, width: contentView.frame.width-42, height: contentView.frame.height)
self.label.font = UIFont(name: "PlayfairDisplay-Regular", size: 18)
button.frame = CGRect(x:10, y: contentView.frame.height/2-8, width: 16, height: 16)
button.setImage(UIImage(named: "CheckboxUnchecked"), for: .normal)
button.setImage(UIImage(named: "CheckboxChecked"), for: .selected)
button.setImage(UIImage(named: "CheckboxUnchecked"), for: .highlighted)
}
}
Issue as mentioned is only this : After first tap it is deselecting automatically.
What's exactly happening is in didSelectRowAt when you reload that indexPath, that cell is deselected automatically and didDeselectRowAt method is called where cell.button.isSelected = false removes the checkmark.
So, to fix this comment out the below lines in didSelectRowAt method.
self.expandableTableView.beginUpdates()
self.expandableTableView.reloadRows(at: [indexPath], with: .automatic)
self.expandableTableView.endUpdates()
Also, reset button's selected state in cell's prepareForReuse() method. This will fix the undefined behaviour where checkbox is selected randomly or after first or second taps.
override func prepareForReuse() {
super.prepareForReuse()
button.isSelected = false
}

How to get the get a index.row and index section from a UITableViewCell with an UIStepper programmatically using Swift 4 [duplicate]

I have table view cells like quiz. And in each cell I have a buttons And how can I identify in which cell button was pressed. Maybe by IndexPath???
This is how I connected button to
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "QuestionCell")!
variant1 = cell.contentView.viewWithTag(1) as! UIButton
variant2 = cell.contentView.viewWithTag(2) as! UIButton
variant3 = cell.contentView.viewWithTag(3) as! UIButton
variant4 = cell.contentView.viewWithTag(4) as! UIButton
variant1.addTarget(self, action: #selector(self.variant1ButtonPressed), for: .touchUpInside)
variant2.addTarget(self, action: #selector(self.variant2ButtonPressed), for: .touchUpInside)
variant3.addTarget(self, action: #selector(self.variant3ButtonPressed), for: .touchUpInside)
variant4.addTarget(self, action: #selector(self.variant4ButtonPressed), for: .touchUpInside)
return cell
}
func variant1ButtonPressed() {
print("Variant1")
variant1.backgroundColor = UIColor.green
}
func variant2ButtonPressed() {
print("Variant2")
variant2.backgroundColor = UIColor.green
}
func variant3ButtonPressed() {
print("Variant3")
variant3.backgroundColor = UIColor.green
}
func variant4ButtonPressed() {
print("Variant4")
variant4.backgroundColor = UIColor.green
}
This is how it looks like in Storyboard:
You should use delegate pattern, basic example:
protocol MyCellDelegate {
func didTapButtonInside(cell: MyCell)
}
class MyCell: UITableViewCell {
weak var delegate: MyCellDelegate?
func buttonTapAction() {
delegate?.didTapButtonInside(cell: self)
}
}
class ViewController: MyCellDelegate {
let tableView: UITableView
func didTapButtonInside(cell: MyCell) {
if let indexPath = tableView.indexPath(for: cell) {
print("User did tap cell with index: \(indexPath.row)")
}
}
}
Use this line to get indexPath, Where you have to pass UIButton on target selector
func buttonTapped(_ sender:AnyObject) {
let buttonPosition:CGPoint = sender.convert(CGPointZero, to:self.tableView)
let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
}
Since actions need to be inside the view controller, ctrl + drag from your button to the view controller - this will use the responder chain.
Basically you need to convert the view (button) to the coordinate system of the table view in order to tell what is the IndexPath and if you have the IndexPath you have the object that corresponds to the button inside the cell that was tapped:
#IBAction func buttonTapped(_ sender: Any) {
if let indexPath = indexPath(of: sender) {
// Your implementation...
}
}
private func indexPath(of element:Any) -> IndexPath? {
if let view = element as? UIView {
// Converting to table view coordinate system
let pos = view.convert(CGPoint.zero, to: self.tableView)
// Getting the index path according to the converted position
return tableView.indexPathForRow(at: pos) as? IndexPath
}
return nil
}
It is important to mention that there many solutions for your question. But you should know that in Apple's sample projects they also use this technic.
This is how you add tag to a UIButton inside UITableView, add below lines of code in
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
cell.yourButton.tag = indexPath.row
cell.yourButton.addTarget(self, action:#selector(btnPressed(sender:)), for: .touchUpInside)
Add this function in your ViewController
func btnPressed(sender: UIButton)
{
print("Button tag \(sender.tag)")
}
Hope this helps...
Simple Subclass button just like JSIndexButton
class JSIndexButton : UIButton {
var indexPath : IndexPath!
}
Now at cellForRowAt
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ItemCell
let itemCategory = dataList[button.indexPath.section];
let item = itemCategory.items[button.indexPath.row];
cell.imgView.setImageWithURL(item.photoUrl);
cell.btnBuy.indexPath = indexPath;
cell.btnBuy.addTarget(self, action: #selector(JSCollapsableTableView.btnBuyPressed(_:)), for: UIControlEvents.touchUpInside)
return cell;
}
Check Button Action
#IBAction func btnBuyPressed(_ button: JSIndexButton) {
let itemCategory = dataList[button.indexPath.section];
let item = itemCategory.items[button.indexPath.row];
}
#objc func ItemsDescription(_ sender: UIButton?,event: AnyObject?) {
let touches: Set<UITouch>
touches = (event?.allTouches!)!
let touch:UITouch = (touches.first)!
let touchPosition:CGPoint = touch.location(in: self.tableView)
let indexPath:NSIndexPath = self.tableView.indexPathForRow(at: touchPosition)! as NSIndexPath
}
adding target
cell.ItemsDescription.addTarget(self, action: #selector(ItemsDescription(_:event:)), for: UIControlEvents.touchUpInside)

Swift Change label text color on tap from within TableViewCell

I have a UILabel that is inside a TableView, I want to change the color of the UILabel to red on user tap. I am using a UITapGestureRecognizer and on tapping the UILabel I can get the content of the UILabel but I can't get the actual UILabel since to my knowledge you can't have parameters inside a UIGesture function.
This is my code and it will help clear things up
class HomeProfilePlacesCell: NSObject {
var Post = [String]()
#objc func PostTap(_ sender: UIGestureRecognizer) {
print(Post[(sender.view?.tag)!])
}
func HomeProfilePlaceTVC(_ tableView: UITableView, cellForRowAt indexPath: IndexPath, streamsModel : streamModel,HOMEPROFILE: HomeProfile, controller: UIViewController) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeTVC", for: indexPath) as! HomeTVC
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(PostTap(_:)))
tapGesture.delegate = self as? UIGestureRecognizerDelegate
cell.post.addGestureRecognizer(tapGesture)
cell.post.text = streamsModel.Posts[indexPath.row]
cell.post.tag = indexPath.row
Post = streamsModel.Posts
return cell
}
}
My function there is PostTap whenever a user taps the UILabel which is the cell.post then I can read it's content inside PostTap but in order to change the color of that UILabel then I'll have to pass the let cell constant into the PostTap function.
Is there anyway I can do that or a work around ? I am new to Swift
Use TableView Delegates: [SWIFT 4.0]
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let cell = tableView.cellForRowAtIndexPath(indexPath) as! <your Custom Cell>
cell.<your CustomCell label name>.textColor = UIColor.red
//OR
cell.<your Customcell label name>.backgroundColor = UIColor.green
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
}
func tableView(tableView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath)
{
let cell = tableView.cellForRowAtIndexPath(indexPath) as! <your Custom Cell>
// change color back to whatever it was
cell.<your Customcell label name>.textColor = UIColor.black
//OR
cell.<your Customcell label name>.backgroundColor = UIColor.white
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
}
Add tag to cell as indexPath.row
cell.tag = indexPath.row
Then
#objc func PostTap(_ sender: UIGestureRecognizer) {
let cell = self.tableVIew.cellForRow(at: sender.tag) as! HomeTVC
// Now you access your cell label here, and can do whatever you want
}
you can make it possible by using
tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath)
when user tap on a cell this method called
in this method do this
tableView.cellForRow(at: indexPath)
this will give you cell cast it as your cell class
and now u can do anything with your label in that cell
cell.label....
To change the color of clicked index label first you need to declare on varible to identify the clicked position
var selectedCellIndex = "" // initialize as empty string
In you cellForRowAt
func HomeProfilePlaceTVC(_ tableView: UITableView, cellForRowAt indexPath: IndexPath, streamsModel : streamModel,HOMEPROFILE: HomeProfile, controller: UIViewController) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeTVC", for: indexPath) as! HomeTVC
cell.post.text = streamsModel.Posts[indexPath.row]
cell.post.tag = indexPath.row
cell.post.isUserInteractionEnabled = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(PostTap(_:)))
tapGesture.delegate = self as? UIGestureRecognizerDelegate
cell.post.addGestureRecognizer(tapGesture)
Post = streamsModel.Posts
if self.selectedCellIndex == "\(indexPath.row)" {
cell.post.text = UIColor.red
} else {
cell.post.text = UIColor.blue
}
return cell
}
In your Tap function
func PostTap(_ sender:UIGestureRecognizer){
let tapView = gesture.view!
let index = tapView.tag
self. selectedCellIndex = "\(index)"
self.YOUR_TABLE_NAME.reloadData()
}
Hope this will help you
Try Closure approach in Cell:
In Custom Table View cell:
class HomeTVC: UITableViewCell {
#IBOutlet weak var labelPost: UILabel!
var callBackOnLabelTap: (()->())?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(postTap(_:)))
tapGesture.numberOfTapsRequired = 1
tapGesture.delegate = self
self.labelPost.addGestureRecognizer(tapGesture)
}
#objc func postTap(_ sender: UIGestureRecognizer) {
self.callBackOnLabelTap?()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Then in cellForRowAt indexPath :
func HomeProfilePlaceTVC(_ tableView: UITableView, cellForRowAt indexPath: IndexPath, streamsModel : streamModel,HOMEPROFILE: HomeProfile, controller: UIViewController) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeTVC", for: indexPath) as! HomeTVC
cell.callBackOnLabelTap = {
cell.labelPost.backgroundColor = UIColor.black
}
return cell
}
For me, I wanted the color for the label to change when the container cell of a label is tapped.
You can select what color you want for the Label text, when tapped by selecting, Highlighted (in Attributes inspector) for Label. From drop down you can select the color you want to see when the cell was tapped.
Attributes Inspector: Highlighted Property for label

Resources