UIButton interaction is not smooth when used in UICollectionViewCell - ios

I Have a UICollectionViewCell in which I have added UIButton. Normally button action gets called but some times it does not. When same button I add in a viewcontroller the interaction is very smooth. Even a gentle tap trigger the action.
Below is the code for button :
func makeTapButton(for superView: UIView) -> UIButton {
let offSetValue = 15
let button = UIButton()
button.backgroundColor = UIColor.yellow
superView.addSubview(button)
button.snp.makeConstraints { (make) in
make.leading.equalToSuperview().offset(-offSetValue)
make.trailing.equalToSuperview().offset(offSetValue)
make.top.equalToSuperview().offset(-offSetValue)
make.bottom.equalToSuperview().offset(offSetValue)
}
return button
}
func setupCustomView() {
self.addSubview(containerStackView)
containerStackView.snp.makeConstraints { (make) -> Void in
make.top.equalTo(self)
make.leading.equalTo(self)
make.trailing.equalTo(self)
make.bottom.equalTo(self)
}
containerStackView.addArrangedSubview(commentStack)
containerStackView.addArrangedSubview(retweetStack)
containerStackView.addArrangedSubview(likeStack)
commentStack.addArrangedSubview(commentImageView)
commentStack.addArrangedSubview(commentsCountLabel)
retweetStack.addArrangedSubview(retweetImageView)
retweetStack.addArrangedSubview(retweetCountLabel)
likeStack.addArrangedSubview(likeImageView)
likeStack.addArrangedSubview(likesCountLabel)
likeButton = makeTapButton(for: likeStack)
commentButton = makeTapButton(for: commentStack)
retweetButton = makeTapButton(for: retweetStack)
}

try below mentioned code when using UIbutton placed in collectionview
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:UICollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath as IndexPath) as! UICollectionViewCell
cell.btnName.addTarget(self, action: #selector(btnSelClk), for: .touchUpInside)
cell.binSel.tag = collectionView.tag
cell.binSel.accessibilityValue = String(indexPath.row)
return cell
}
#objc func btnSelClk(sender:UIButton) {
selectAry[sender.tag] = sender.accessibilityValue!
// your button action
}

Defining your buttons in UICollectionViewCell class and your functions in UIViewController class being less laggy because they are reused;
import UIKit
class YourCell: UITableViewCell {
#IBOutlet weak var yourBtn: UIButton!
var yourButtonAction: (() -> ())?
#IBAction func buttonPressed(_ sender: UISlider) {
yourButtonAction()
}
}
then in your ViewController where you call your cell;
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourCell", for: indexPath) as! YourCell
cell.yourBtn = {[unowned self] in
// call your functions here, I hope this will be less laggy
print("button pressed")
}
}

Related

iOS swift: UICollectionview horizontal scroll single cell not reloading

In my application UICollection scroll horizontally. collection-view cell two button and one UIView was designed.
Each cell loaded two button. when user click one button the particular cell should be reload and the UIView will be displayed in that cell only other cell not displayed.
Here i attached the collectionview image:
Here my code:
#IBOutlet weak var dataCollectionView: UICollectionView!
var addIndexArray:[Int] = []
var arraySelectedFilterIndex = [IndexPath]()
self.listArr = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t"]
override func viewDidLoad() {
super.viewDidLoad()
self.dataCollectionView.reloadData()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return (lvsnListArr.count/2)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = dataCollectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier_CollectionView, for: indexPath as IndexPath) as! DataCell
if self.arraySelectedFilterIndex.contains(indexPath) {
cell.buttonView.isHidden = false
}else{
cell.buttonView.isHidden = true
}
cell.btn1.setTitle(lvsnListArr[2 * indexPath.row], for: .normal)
cell.btn1.tag = indexPath.row
cell.btn1.addTarget(self, action: #selector(btnPressed(sender:)), for: .touchUpInside)
cell.btn2.setTitle(lvsnListArr[2 * indexPath.row + 1], for: .normal)
cell.btn2.tag = indexPath.row
cell.btn2.addTarget(self, action: #selector(btn2Pressed(sender:)), for: .touchUpInside)
return cell
}
#objc func btnPressed(sender: UIButton) {
self.addIndexArray.append(sender.tag)
let hitPoint = sender.convert(CGPoint.zero, to: dataCollectionView)
if let indexPath = dataCollectionView.indexPathForItem(at: hitPoint) {
print("indexPath--->",indexPath)
self.arraySelectedFilterIndex.append(getIndexPath)
self.dataCollectionView.reloadItems(at: [getIndexPath])
}
}
#objc func btn2Pressed(sender: UIButton) {
self.addIndexArray.append(sender.tag)
let hitPoint = sender.convert(CGPoint.zero, to: dataCollectionView)
if let indexPath = dataCollectionView.indexPathForItem(at: hitPoint) {
print("indexPath--->",indexPath)
self.arraySelectedFilterIndex.append(getIndexPath)
self.dataCollectionView.reloadItems(at: [getIndexPath])
}
}
My error:
I clicked cell btn1 one action btnPressed single cell over load and display the next cell image both images are overlap in collectionview.
Here i attached my issue cell image.
Here i got cell indexpath and indexpath.row, how can i validate and fix this issue in cell for row. struggling this point.
Kinldy help to fix this issues. Thanks advance.
You can reload single cell like you are doing in button action
self.dataCollectionView.reloadItems(at: [getIndexPath])
OR
You can get cell in button action like as below
if let cell = self.dataCollectionView.cellForItem(at: indexPath) as? DataCell
{
//Here you can write your view hide show code
if self.arraySelectedFilterIndex.contains(indexPath)
{
cell.buttonView.isHidden = false
}
else
{
cell.buttonView.isHidden = true
}
}

uibutton in collectionview cell action duplicating

So basically my problem is that when I click on a button which is present in collection view cell it should change the colour of button background colour. but the problem is it is changing the colour of another button. eg if I click on button 1 it changes the colour of button 6 automatically.
class hello: UICollectionViewCell {
#IBOutlet weak var btn: UIButton!
#IBAction func click(_ sender: Any) {
if btn.isSelected == true
{
btn.backgroundColor = UIColor.red
btn.isSelected = false
}
else{ btn.backgroundColor = UIColor.purple
btn.isSelected = true
}
}
override func prepareForReuse() {
super.prepareForReuse()
}
}
view controller file
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "happy", for: indexPath) as! hello
if cell.btn.isSelected
{
cell.btn.backgroundColor = UIColor.red
}
else{ cell.btn.backgroundColor = UIColor.purple
}
cell.btn.tag = indexPath.item
print(cell.btn.isSelected ,indexPath.row)
return cell
}
The problem is that the UICollectionView re-uses cell for optimized scroll performance. Hence it re-uses the cell at index 1 when displaying cell at index 6 for e.g. Therefore you need to set the state of the cell when ever it is updated/reused.
The following function is called everytime. So you need to set cell.btn. backgroundColor over here.
func collectionView(_ collectionView: UICollectionView, cellForItemAt
indexPath: IndexPath) -> UICollectionViewCell {
...
...
if dataSource[indexPath.row].selected {
btn.backgroundColor = UIColor.red
}else {
btn.backgroundColor = UIColor.purple
}
...
return cell
}
Now, it is upto your individual implementation, how you want to update the model when selection is changed. One option is you can define a protocol and implement it in your ViewController to update the values.

Get index of clicked UICollectionViewCell in UICollectionView Swift

How do I get the index of the "Sheep" I clicked on in a CollectionView made in Xcode with Swift for iOS?
class SheepsOverviewVC:
UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "class", for: indexPath) as! ClassesCollectionCell
if(sheeps.count > 0) {
cell.ClassImageView.image = UIImage(named: sheeps[indexPath.row] as! String)
cell.SheepName.text = names[indexPath.row] as? String
}
return cell
}
I created a Sent Event on the TouchDown via the Gui:
#IBAction func clickingSheep(_ sender: UIButton) {
print("This will show info about the Sheep")
print(sender)
}
But the response I get is from the second print:
<UIButton: 0x7f9a63021d20; frame = (50 50; 136 169); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x60800003d260>>
Probably there is some way to figure out which Sheep was clicked, but how do I get that information?
This is how it looks like (other namings then provided in the post):
One solution is to get the index path of the cell based on the button's location.
#IBAction func clickingSheep(_ sender: UIButton) {
let hitPoint = sender.convert(CGPoint.zero, to: collectionView)
if let indexPath = collectionView.indexPathForItem(at: hitPoint) {
// use indexPath to get needed data
}
}
You can set and check the button property "tag" (if you have the outlet set to the controller)
Here is another easy solution:
Have a new property for the callback.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "class", for: indexPath) as! ClassesCollectionCell
if(sheeps.count > 0) {
cell.ClassImageView.image = UIImage(named: sheeps[indexPath.row] as! String)
cell.SheepName.text = names[indexPath.row] as? String
}
cell.callBack = { [weak self] collectionViewCell in
let indexPath = collectionView.indexPath(for: collectionViewCell)
self?.doStuffFor(indexPath)
}
return cell
}
and on the cell you can have the ibaction
cell class
//...
var callBack : ((UICollectionViewCell?)->Void)?
//...
#IBAction func action(_ sender: UIButton) {
self.callBack?(self)
}

Swift 3- How to get button in UICollectionViewCell work

I am trying to implement an Edit button inside a cell.
Please refer to image:
What I done so far:
MainController:
class MainController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
let imgCellId = "imgCellId"
override func viewDidLoad() {
collectionView?.backgroundColor = .white
collectionView?.register(ImgItemCell.self, forCellWithReuseIdentifier: imgCellId)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: imgCellId, for: indexPath) as! ImgItemCell
cell.editButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
return cell
}
func buttonPressed(){
print("buttonPressed !")
}
}
ImgItemCell:
import Material
class ImgItemCell: UICollectionViewCell{
override init(frame: CGRect){
super.init(frame: frame)
setupViews()
}
...
let editButton: RaisedButton = {
let button = RaisedButton(title: "Edit", titleColor: .black) return button
}()
func setupViews(){
...
addSubview(editButton)
...
}
}
Result: The button is not clickable. No log is printed when clicking on the button.
In android, I have done this by OnClickListener of button to perform action for each row. How can I do the same in Swift 3?
Solution: (it's working for me)
Hi all thank you for all suggestions, they’re more less the hint for me to come to the solution.
The root cause of my problem is view hierarchy (as #DatForis pointed out)
Explanation: I want a cell contains image and a layout of buttons so that I had view hierarchy as below
override func setupViews() {
super.setupViews()
addSubview(imgView)
addSubview(buttonLayout)
buttonLayout.addSubView(buttonList)
buttonList.addSubview(editButton)
buttonList.addSubview(shareButton)
}
this hierarchy somehow blocked the click event of button.
Therefore, I changed a bit in hierarchy
override func setupViews() {
super.setupViews()
addSubview(imgView)
addSubview(buttonLayout)
buttonLayout.addSubview(editButton)
buttonLayout.addSubview(shareButton)
}
and BAM ! it worked like a charm.
In fact, I need a proper explanation about why the hierarchy impact to children view.
By the way, I think most replies here are workable solution, but I selected #DonMag as final answer, because it’s clean and clear with a cool callback to Controller.
But again, my root problem is from view hierarchy.
A very reliable and flexible pattern is to assign a "Callback Closure" to your cell. Put your button action handler inside the cell, and have it "call back" to the view controller.
Here is a basic example (you should be able to implement it with your custom cell with no problem):
//
// CViewWithButtonCollectionViewController.swift
// SWTemp2
//
// Created by Don Mag on 6/5/17.
// Copyright © 2017 DonMag. All rights reserved.
//
import UIKit
private let reuseIdentifier = "ImgItemCell"
class ImgItemCell: UICollectionViewCell {
// this will be our "call back" action
var btnTapAction : (()->())?
override init(frame: CGRect){
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupViews()
}
let editButton: UIButton = {
let button = UIButton(type: UIButtonType.system)
button.translatesAutoresizingMaskIntoConstraints = false
button.backgroundColor = .white
button.setTitle("Edit", for: .normal)
return button
}()
func setupViews(){
// add a button
addSubview(editButton)
editButton.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
editButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
// add the touchUpInside target
editButton.addTarget(self, action: #selector(btnTapped), for: .touchUpInside)
}
#objc func btnTapped() {
print("Tapped!")
// use our "call back" action to tell the controller the button was tapped
btnTapAction?()
}
}
class CViewWithButtonCollectionViewController: UICollectionViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let layout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
layout.itemSize = CGSize(width: 300, height: 100)
}
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! ImgItemCell
cell.backgroundColor = .red
// set a "Callback Closure" in the cell
cell.btnTapAction = {
() in
print("Edit tapped in cell", indexPath)
// start your edit process here...
}
return cell
}
}
You might want to use a tag for a simpler approach, but I always implement a delegate pattern in the case of buttons inside cells
protocol MyCollectionViewCellDelegate: class {
func button(wasPressedOnCell cell: MyCollectionViewCell)
}
class MyCollectionViewCell: UICollectionViewCell {
weak var delegate: MyCollectionViewCellDelegate?
var data: String = "DATA"
#IBAction func buttonWasPressed(sender: UIButton){
delegate?.button(wasPressedOnCell: self)
}
}
class MainViewController: UIViewController, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "reuse", for: indexPath) as! MyCollectionViewCell
cell.delegate = self
return cell
}
}
extension MainViewController: MyCollectionViewCellDelegate{
func button(wasPressedOnCell cell: MyCollectionViewCell) {
//do what you want with the cell and data
}
}
Using this method will allow you to have multiple buttons inside a cell. Use a different delegate method for each button
I have created the same scenario. The only difference is that I have used UIButton instead of RaisedButton. And it is working perfectly fine.
1.ImgItemCell
class ImgItemCell: UICollectionViewCell
{
//MARK: View Lifecycle Methods
override func awakeFromNib()
{
super.awakeFromNib()
setupViews()
}
let editButton: UIButton = {
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 50))
button.setTitle("Edit", for: .normal)
return button
}()
func setupViews()
{
addSubview(editButton)
}
}
2.MainController methods
//MARK: UICollectionViewDataSource
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: imgCellId, for: indexPath) as! ImgItemCell
cell.editButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
return cell
}
#objc func buttonPressed()
{
print("buttonPressed !")
}
How your buttonpress method will know,you are selecting which cell button.So you can differentiate with tag
Add in cellForItemAtindexPath
ButtonObject.tag = indexPath.item
and
func buttonPressed(_ sender: UIButton)
{
print("buttonPressed ! \(sender.tag)")
}
If touch action on UIButton is not detecting.
To enable touch action on the UIButton of your Custom UICollectionCell, add the below method in your Custom UICollectionCell class.
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
var view = myButton.hitTest(myButton.convert(point, from: self), with: event)
if view == nil {
view = super.hitTest(point, with: event)
}
return view
}
func setupViews() {
...
addSubview(editButton)
editButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
}
func buttonPressed(sender:UIButton){
print("buttonPressed !")
}

get indexPath of UITableViewCell on click of Button from Cell

I have a button (red color cross) in the UITableViewCell and on click of that button I want to get indexPath of the UITableViewCell.
Right now I am assigning tag to each of the button like this
cell.closeButton.tag = indexPath.section
and the on click of the button I get the indexPath.section value like this:
#IBAction func closeImageButtonPressed(sender: AnyObject) {
data.removeAtIndex(sender.tag)
tableView.reloadData()
}
Is this the right way of implementation or is there any other clean way to do this?
Use Delegates:
MyCell.swift:
import UIKit
//1. delegate method
protocol MyCellDelegate: AnyObject {
func btnCloseTapped(cell: MyCell)
}
class MyCell: UICollectionViewCell {
#IBOutlet var btnClose: UIButton!
//2. create delegate variable
weak var delegate: MyCellDelegate?
//3. assign this action to close button
#IBAction func btnCloseTapped(sender: AnyObject) {
//4. call delegate method
//check delegate is not nil with `?`
delegate?.btnCloseTapped(cell: self)
}
}
MyViewController.swift:
//5. Conform to delegate method
class MyViewController: UIViewController, MyCellDelegate, UITableViewDataSource,UITableViewDelegate {
//6. Implement Delegate Method
func btnCloseTapped(cell: MyCell) {
//Get the indexpath of cell where button was tapped
let indexPath = self.collectionView.indexPathForCell(cell)
print(indexPath!.row)
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell") as! MyCell
//7. delegate view controller instance to the cell
cell.delegate = self
return cell
}
}
How to get cell indexPath for tapping button in Swift 4 with button selector
#objc func buttonClicked(_sender:UIButton){
let buttonPosition = sender.convert(CGPoint.zero, to: self.tableView)
let indexPath = self.tableView.indexPathForRow(at:buttonPosition)
let cell = self.tableView.cellForRow(at: indexPath) as! UITableViewCell
print(cell.itemLabel.text)//print or get item
}
Try with the best use of swift closures : Simple, Quick & Easy.
In cellForRowAtIndexPath method:
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCellIdentifier", for: indexPath) as! CustomCell
cell.btnTick.mk_addTapHandler { (btn) in
print("You can use here also directly : \(indexPath.row)")
self.btnTapped(btn: btn, indexPath: indexPath)
}
Selector Method for external use out of cellForRowAtIndexPath method:
func btnTapped(btn:UIButton, indexPath:IndexPath) {
print("IndexPath : \(indexPath.row)")
}
Extension for UIButton :
extension UIButton {
private class Action {
var action: (UIButton) -> Void
init(action: #escaping (UIButton) -> Void) {
self.action = action
}
}
private struct AssociatedKeys {
static var ActionTapped = "actionTapped"
}
private var tapAction: Action? {
set { objc_setAssociatedObject(self, &AssociatedKeys.ActionTapped, newValue, .OBJC_ASSOCIATION_RETAIN) }
get { return objc_getAssociatedObject(self, &AssociatedKeys.ActionTapped) as? Action }
}
#objc dynamic private func handleAction(_ recognizer: UIButton) {
tapAction?.action(recognizer)
}
func mk_addTapHandler(action: #escaping (UIButton) -> Void) {
self.addTarget(self, action: #selector(handleAction(_:)), for: .touchUpInside)
tapAction = Action(action: action)
}
}
In Swift 4 , just use this:
func buttonTapped(_ sender: UIButton) {
let buttonPostion = sender.convert(sender.bounds.origin, to: tableView)
if let indexPath = tableView.indexPathForRow(at: buttonPostion) {
let rowIndex = indexPath.row
}
}
You can also get NSIndexPath from CGPoint this way:
#IBAction func closeImageButtonPressed(sender: AnyObject) {
var buttonPosition = sender.convertPoint(CGPointZero, to: self.tableView)
var indexPath = self.tableView.indexPathForRow(atPoint: buttonPosition)!
}
Create a custom class of UIButton and declare a stored property like this and use it to retrieve assigned indexPath from callFroRowAtIndexPath.
class VUIButton: UIButton {
var indexPath: NSIndexPath = NSIndexPath()
}
This is the full proof solution that your indexPath will never be wrong in any condition. Try once.
//
// ViewController.swift
// Table
//
// Created by Ngugi Nduung'u on 24/08/2017.
// Copyright © 2017 Ngugi Ndung'u. All rights reserved.
//
import UIKit
class ViewController: UITableViewController{
let identifier = "cellId"
var items = ["item1", "2", "3"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.title = "Table"
tableView.register(MyClass.self, forCellReuseIdentifier: "cellId")
}
//Return number of cells you need
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! MyClass
cell.controller = self
cell.label.text = items[indexPath.row]
return cell
}
// Delete a cell when delete button on cell is clicked
func delete(cell: UITableViewCell){
print("delete")
if let deletePath = tableView.indexPath(for: cell){
items.remove(at: deletePath.row)
tableView.deleteRows(at: [deletePath], with: .automatic)
}
}
}
class MyClass : UITableViewCell{
var controller : ViewController?
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setUpViews()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
fatalError("init(coder:) has not been implemented")
}
let label : UILabel = {
let label = UILabel()
label.text = "My very first cell"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let btn : UIButton = {
let bt = UIButton(type: .system)
bt.translatesAutoresizingMaskIntoConstraints = false
bt.setTitle("Delete", for: .normal)
bt.setTitleColor(.red, for: .normal)
return bt
}()
func handleDelete(){
controller?.delete(cell: self)
}
func setUpViews(){
addSubview(label)
addSubview(btn)
btn.addTarget(self, action: #selector(MyClass.handleDelete), for: .touchUpInside)
btn.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
label.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 16).isActive = true
label.widthAnchor.constraint(equalTo: self.widthAnchor , multiplier: 0.8).isActive = true
label.rightAnchor.constraint(equalTo: btn.leftAnchor).isActive = true
}
}
Here is a full example that will answer your question.
In your cellForRow:
#import <objc/runtime.h>
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
setAssociatedObject(object: YOURBUTTON, key: KEYSTRING, value: indexPath)
}
#IBAction func closeImageButtonPressed(sender: AnyObject) {
let val = getAssociatedObject(object: sender, key: KEYSTROKING)
}
Here val is your indexPath object, your can pass any object like you can assign pass cell object and get it in button action.
try this:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = (tableView.dequeueReusableCell(withIdentifier: "MainViewCell", forIndexPath: indexPath) as! MainTableViewCell)
cell.myButton().addTarget(self, action: Selector("myClickEvent:event:"), forControlEvents: .touchUpInside)
return cell
}
this function get the position of row click
#IBAction func myClickEvent(_ sender: Any, event: Any) {
var touches = event.allTouches()!
var touch = touches.first!
var currentTouchPosition = touch.location(inView: feedsList)
var indexPath = feedsList.indexPathForRow(atPoint: currentTouchPosition)!
print("position:\(indexPath.row)")
}
class MyCell: UICollectionViewCell {
#IBOutlet weak var btnPlus: UIButton!
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->
UITableViewCell {
cell.btnPlus.addTarget(self, action: #selector(increment_Action(sender:)),
for: .touchUpInside)
cell.btnPlus.tag = indexPath.row
cell.btnPlus.superview?.tag = indexPath.section
}
#objc func increment_Action(sender: UIButton) {
let btn = sender as! UIButton
let section = btn.superview?.tag ?? 0
let row = sender.tag
}

Resources