Swift 3.0 : Custom CollectionView header button click - ios

I have made a custom collectionview cell. I have placed it as the header of the collection view through this code:
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionElementKindSectionHeader {
let cell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "HeaderCell", for: indexPath) as! GridHeaderCollectionViewCell
cell.pagePluginBtn.tag = 0
cell.tag = 0
cell.nameLabel.text = pageRecord["GroupName"] as? String
cell.pagePluginBtn.addTarget(self, action: #selector(TappedOnPagePluginBtn(sender:)), for: .touchUpInside)
return cell
}
abort()
}
func TappedOnPagePluginBtn(sender:UIButton){
print("in plugin")
}
The cell is defined as:
class GridHeaderCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var pagePluginBtn: UIButton!
}
The TappedOnPagePluginBtn() is not getting called at all. Is there any way to make buttons clickable in the headerView of collectionView?

A second way (not second, a better version of mine) is from AlexLittlejohn, creator of ALCameraViewController.
You can create a UIButton extension to add actions like adding targets.
typealias ButtonAction = () -> Void
extension UIButton {
private struct AssociatedKeys {
static var ActionKey = "ActionKey"
}
private class ActionWrapper {
let action: ButtonAction
init(action: #escaping ButtonAction) {
self.action = action
}
}
var action: ButtonAction? {
set(newValue) {
removeTarget(self, action: #selector(performAction), for: .touchUpInside)
var wrapper: ActionWrapper? = nil
if let newValue = newValue {
wrapper = ActionWrapper(action: newValue)
addTarget(self, action: #selector(performAction), for: .touchUpInside)
}
objc_setAssociatedObject(self, &AssociatedKeys.ActionKey, wrapper, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
get {
guard let wrapper = objc_getAssociatedObject(self, &AssociatedKeys.ActionKey) as? ActionWrapper else {
return nil
}
return wrapper.action
}
}
#objc func performAction() {
guard let action = action else {
return
}
action()
}
}
then;
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerReuseIdentifier, for: indexPath) as! GridHeaderCollectionViewCell
view.pagePluginBtn.action = {
print("yeah we catch it!")
}
return view
}

Change your cell class like this:
public typealias ButtonAction = () -> Void
class GridHeaderCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var pagePluginBtn: UIButton!
var pagePluginButtonAction : ButtonAction?
override func viewDidLoad(){
pagePluginBtn.addTarget(self, action: #selector(pagePluginBtnClick(_:)), for: .touchUpInside)
}
#objc func pagePluginBtnClick(_ sender : UIButton){
guard let pagePluginButtonAction = pagePluginButtonAction else{
return
}
pagePluginButtonAction()
}
}
Than all you need to do is:
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerReuseIdentifier, for: indexPath) as! GridHeaderCollectionViewCell
view.pagePluginButtonAction = {
self.TappedOnPagePluginBtn()
}
return view
}
func TappedOnPagePluginBtn(){
print("in plugin")
}

Related

Is it wrong to add action to button in tableViewCell with tag?

I have a UItableViewCell with a button inside it, I set the tag of the button and add the action of the button in my ViewController using the tag.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "BillHistoryTableViewCell", for: indexPath) as! BillHistoryTableViewCell
let cellData = billHistories[indexPath.row]
cell.setup(with: cellData)
cell.retryButton.tag = indexPath.row
return cell
}
#IBAction func billHistoryRetryButtonDidTap(_ sender: UIButton) {
let index = sender.tag
if let id = billHistories[index].transactionInfo?.billUniqueID {
hidePayIdGeneralTextField()
billIdTextField.text = id.toNormalNumber()
inquiryGeneralBillRequest()
}
}
I want to know is it wrong for any reason? someone told me it is not good because it uses lots of memory to use tags.
Will it work? yes, but as mentioned above, this is not the best approach, I'd avoid using tags unless this is just for some POC. There are better approaches to handle it.
The first I'd suggest is using delegation to inform back to the controller, here's an example:
class BillHistoryTableViewController {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "BillHistoryTableViewCell", for: indexPath) as! BillHistoryTableViewCell
let cellData = billHistories[indexPath.row]
cell.setup(with: cellData)
cell.index = indexPath.row
cell.delegate = self
return cell
}
}
extension BillHistoryTableViewController: BillHistoryTableViewCellDelegate {
func didTapButton(index: Int) {
print("tapped cell with index:\(index)")
if let id = billHistories[index].transactionInfo?.billUniqueID {
hidePayIdGeneralTextField()
billIdTextField.text = id.toNormalNumber()
inquiryGeneralBillRequest()
}
}
}
protocol BillHistoryTableViewCellDelegate: AnyObject {
func didTapButton(index: Int)
}
class BillHistoryTableViewCell: UITableViewCell {
weak var delegate: BillHistoryTableViewCellDelegate?
var cellData: CellData?
var index: Int?
func setup(with cellData: CellData) {
self.cellData = cellData
}
#IBAction func buttonPressed(_ sender: UIButton) {
guard let index = index else {
return
}
delegate?.didTapButton(index: index)
}
}
Another approach that I prefer lately is using Combine's PassThroughSubject, it requires less wiring and delegate definitions.
import Combine
class BillHistoryTableViewController {
var cancellable: AnyCancellable?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "BillHistoryTableViewCell", for: indexPath) as! BillHistoryTableViewCell
let cellData = billHistories[indexPath.row]
cell.setup(with: cellData)
cell.index = indexPath.row
cancellable = cell.tappedButtonSubject.sink { [weak self] index in
guard let self = self else { return }
print("tapped cell with index:\(index)")
if let id = self.billHistories[index].transactionInfo?.billUniqueID {
self.hidePayIdGeneralTextField()
self.billIdTextField.text = id.toNormalNumber()
self.inquiryGeneralBillRequest()
}
}
return cell
}
}
class BillHistoryTableViewCell: UITableViewCell {
var tappedButtonSubject = PassthroughSubject<Int, Never>()
var cellData: CellData?
var index: Int?
func setup(with cellData: CellData) {
self.cellData = cellData
}
#IBAction func buttonPressed(_ sender: UIButton) {
guard let index = index else {
return
}
tappedButtonSubject.send(index)
}
}
You can make it even shorter by injecting the index with the cellData, e.g:
func setup(with cellData: CellData, index: Int) {
self.cellData = cellData
self.index = index
}
but from what I see in your example, you don't even need the index, you just need the CellData, so if we'll take the Combine examples these are the main small changes you'll have to make:
var tappedButtonSubject = PassthroughSubject<CellData, Never>()
tappedButtonSubject.send(cellData)
and observing it by:
cancellable = cell.tappedButtonSubject.sink { [weak self] cellData in
if let id = cellData.transactionInfo?.billUniqueID {
//
}
}

UIButton interaction is not smooth when used in UICollectionViewCell

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

Delegate function from protocol not being called

I have a previously working delegate and protocol that since the conversion to Swift 3 is no longer being called.
protocol TaskCellDelegate {
func doneHit(_ cell : TaskCell)
}
class TaskCell : UITableViewCell {
var delegate : TaskCellDelegate?
#IBOutlet weak var label: UILabel!
#IBOutlet weak var detailLabel: UILabel!
#IBOutlet weak var _checkBox: M13Checkbox!
override func awakeFromNib() {
super.awakeFromNib()
let tap = UITapGestureRecognizer(target: self, action: #selector(TaskCell.buttonClicked(_:)))
tap.numberOfTapsRequired = 1
_checkBox.addGestureRecognizer(tap)
_checkBox.isUserInteractionEnabled = true
_checkBox.markType = .checkmark
_checkBox.boxType = .circle
_checkBox.stateChangeAnimation = .expand(.fill)
}
func buttonClicked(_ sender:UITapGestureRecognizer) {
delegate?.doneHit(self)
}
}
As you can see, when the _checkBox is tapped it should call the function doneHit in my class (not added because it doesn't seem necessary but I can) but I set a breakpoint and it's never called. I've set my delegate and conformed to the protocol in my class but nothing is happening. The doneHit function is supposed to update my backend but its not being called. If you need more info, I can provide.
Edit 1:
class TasksTVC: UITableViewController, TaskCellDelegate {
func doneHit(_ cell:TaskCell) {
if let indexPath = self.tableView.indexPath(for: cell) {
task = tasksInSectionArray[indexPath.section][indexPath.row]
if task.done == false {
cell._checkBox.setCheckState(.checked, animated: true)
task.done = true
task.completedBy = user
cell.detailLabel.text = "Completed By: \(task.completedBy)"
cell.label.textColor = UIColor.gray
print("cell checked")
}
else {
cell._checkBox.setCheckState(.unchecked, animated: true)
task.done = false
task.completedBy = ""
cell.detailLabel.text = ""
cell.label.textColor = UIColor.black
print("cell unchecked")
}
fb.updateTaskDoneBool(ref, taskID: task.id, taskDone: task.done)
fb.updateTaskCompletedBy(ref, taskID: task.id, taskCompletedBy: task.completedBy)
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TaskCell", for: indexPath) as! TaskCell
cell.selectionStyle = .none
task = tasksInSectionArray[indexPath.section][indexPath.row]
cell.label.text = task.title
if task.done == true {
cell._checkBox.setCheckState(.checked, animated: true)
cell.detailLabel.text = "Completed By: \(task.completedBy)"
cell.label.textColor = UIColor.gray
}
else {
cell._checkBox.setCheckState(.unchecked, animated: true)
cell.detailLabel.text = ""
cell.label.textColor = UIColor.black
}
doneHit(cell)
cell.delegate = self
return cell
}}
Looks like you didn't set correctly the delegate property in your TaskCell instance , I will make a very basic example hopefully it helps you to catch the issue:
Result (Edited)
Code
TableViewController
import UIKit
protocol TaskCellDelegate {
func doneHit(_ cell: TaskCell)
}
class TableViewController: UITableViewController, TaskCellDelegate {
func doneHit(_ cell: TaskCell) {
let alert = UIAlertController(
title: "Info",
message: "button touched in cell",
preferredStyle: .alert
)
present(alert, animated: true, completion: nil)
}
}
extension TableViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TaskCell
cell.delegate = self // probably you forgot to set this part?
return cell
}
}
TaskCell (Edited)
Instead creating a new UITapGestureRecognizer to attach to the checkbox, you can use addTarget method to attach event handler for the UIControlEvents.valueChanged value.
import UIKit
import M13Checkbox
class TaskCell: UITableViewCell {
var delegate: TaskCellDelegate?
#IBOutlet weak var checkbox: M13Checkbox!
override func awakeFromNib() {
super.awakeFromNib()
checkbox.addTarget(self, action: #selector(buttonClicked), for: .valueChanged)
}
func buttonClicked() {
delegate?.doneHit(self)
}
}
There are following cases if delegate is not being called:
The action: buttonClicked is not being called.
The View Controller not Conforming to the protocol.
class ViewController: UIViewController, TaskCellDelegate {
The protocol method not implemented inside View Controller.
func doneHit(_ cell : TaskCell) {
print("delegate implementation called")
}
Delegate not assigned in cellForRowAtIndexPathMethod:
cell.delegate = self

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
}

hide button in a collectionview cell when trigger

i have collectionview that contain del button and add
cell.coupon_add.tag = indexPath.row
cell.coupon_add?.layer.setValue(id, forKey: "coupon_id")
cell.coupon_add?.layer.setValue(uID, forKey: "user_id")
cell.coupon_add?.addTarget(self, action: #selector(ViewController.addItem(_:)), forControlEvents: UIControlEvents.TouchUpInside)
func addItem(sender:UIButton) {
let point : CGPoint = sender.convertPoint(CGPointZero, toView:collectionview)
let indexPath = collectionview!.indexPathForItemAtPoint(point)
let cell = collectionview.dequeueReusableCellWithReuseIdentifier("listcell", forIndexPath: indexPath!) as! ListCell
let coupon_id : String = (sender.layer.valueForKey("coupon_id")) as! String
let user_id : String = (sender.layer.valueForKey("user_id")) as! String
if user_id == "empty" {
self.login()
}else{
print("adding item**",indexPath)
cell.coupon_add.hidden = true
cell.coupon_del.hidden = true
let buttonRow = sender.tag
print(buttonRow)
}
}
i want to hide the add button when trigger. i just get the value of the indexPath but i dont know how to hide it without refresh the collectionview
Create a custom cell
class CustomCell: UICollectionViewCell {
#IBOutlet weak var label: UILabel!
#IBOutlet weak var delButton: UIButton!
#IBOutlet weak var addButton: UIButton!
#IBAction func addTapped(sender: AnyObject) {
delButton.removeFromSuperview()
addButton.removeFromSuperview()
}
}
Typical CollectionView Controller
class ViewController: UICollectionViewController {
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10;
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CustomCell
cell.label.text = "Cell \(indexPath.row)"
return cell
}
}
And your button will gone, when you hit them

Resources