Collection View Cell Action using Delegates and Protocols - ios

I have created a View Controller that contains a UITableView and each UITableViewCell contains a UICollectionView.
I made 2 API calls and every collectionView present the first 5 results of each API call.
Also, I added a button on each TableView Header on the right corner with the title "Show All". You can see the screen on the Image below.
Here is how I add the tableView header button:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 100))
let showHideButton: UIButton = UIButton(frame: CGRect(x:headerView.frame.size.width - 80, y:0, width:75, height:35))
showHideButton.setTitle("Show All", for: .normal)
showHideButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 18)
showHideButton.setTitleColor(#colorLiteral(red: 0.9607843137, green: 0.007843137255, blue: 0.03137254902, alpha: 1), for: .normal)
//showHideButton.addTarget(self, action: #selector(btnShowHideTapped), for: .touchUpInside)
headerView.addSubview(showHideButton)
return headerView
}
When I tap on "show all" button on tableView header, I want to jump to another view controller ("showAllViewController") and represent all the result of my object and when I tap on the Image of CollectionViewCell I want to jump to another view controller ("detailsViewController"). How can I do it using delegates and protocols?
Here is an example image with my screen:
Edit: I followed the following steps from this question (navigate on click of collectionview cell inside tableview) but I don't know what I need to write on the "cellTapped()" function:
ViewController.swift :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CategoryRow
cell.delegate = self
return cell
}
MyCell.swift :
protocol CategoryRowDelegate:class {
func cellTapped()
}
CategoryRow.swift :
class CategoryRow : UITableViewCell {
weak var delegate:CategoryRowDelegate?
#IBOutlet weak var collectionView: UICollectionView!
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if delegate!= nil {
delegate?.cellTapped()
}
}
Add the delegate function inside ViewController
func cellTapped(){
//code for navigation
//I don't know what to write
}
Can anybody help me?

First of all I would advise you to insert a tag to the button when you create it, so you know which button in the collection the user clicked on, then add:
showHideButton.tag = section // assign the section number to the tag of the button
then, as you already wrote in the code, you assign an action to the button click:
showHideButton.addTarget(self, action: #selector(self.btnShowHideTapped(sender:)), for: .touchUpInside)
so you're gonna get something like that eventually:
showHideButton.setTitle("Show All", for: .normal)
showHideButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 18)
showHideButton.setTitleColor(#colorLiteral(red: 0.9607843137, green: 0.007843137255, blue: 0.03137254902, alpha: 1), for: .normal)
showHideButton.tag = section // section Number for Header
showHideButton.addTarget(self, action: #selector(self.btnShowHideTapped(sender:)), for: .touchUpInside) // Sender UIButton
And in your function you call back to click =>
#objc func btnShowHideTapped(sender: UIButton) {
print(sender.tag)
// Switch Action if is HeaderView 0 or HeaderView 1 etc...
// self.present(YourViewController...) OR self.performSegue(withIdentifier: "detailsViewController", sender: nil)
}
I hope I've been there for you. Let me know.

1] In separate dataSource method - create protocol
protocol myProductsDelegate: class {
func cellTaped()
}
class ProductsDataSource: NSObject, UICollectionViewDataSource {
var delegate: myProductsDelegate?
// func collectionView(_ collectionView: UICollectionView, //numberOfItemsInSection section: Int) -> Int
// {
// return
// }
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! ProductsCollectionViewCell
return cell
}
2] In separate delegate method -
class ProductsDelegate: NSObject, UICollectionViewDelegate {
var delegate: myProductsDelegate?
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if delegate != nil {
delegate?.cellTaped()
}
}
3] Note: In viewDidload -
self.CollectionView.delegate = self.myDelegate
self.CollectionView.dataSource = self.myDataSource
self.myDelegate.delegate = self
4] In your main view controller where collectionView is available -
var myDelegate: ProductsDelegate = ProductsDelegate()
var myDataSource: ProductsDataSource = ProductsDataSource()
extension MainViewController: ProductsDelegate {
func cellTaped()
{
let vc = storyboard?.instantiateViewController(identifier: "SecondViewController") as? SecondViewController
self.present(vc!, animated: true, completion: nil)
}

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

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.

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

How to access buttons in a UICollectionView from a target function set (Swift 3)

In my View Controller, I have a collection view that, when rendered, displays 3 cells, each of which has a label, and a button. The label displays the name of a color, and the button has a background image that displays a color swatch.
I want it so that whenever you click on one of the buttons, that button gets a dark border around it, while the other buttons get a light border on them, to indicate the clicked-on button as being "selected". Alternately, I could probably do this by changing the image out based on the selected state of the image - but my question remains the same.
How do I access the other two buttons, to toggle their properties?
I have a script implemented that allows me to add a border to the button that somebody clicked on - but I cannot figure out how to access the other buttons, in the other cells of the CollectionView to alter their border properties as well.
Here is my source code (with irrelevant/unrelated bits stripped out)
class trimSelectorVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var trimSelector: UICollectionView!
struct trimObject {
var trimName: String
var trimButton: String
var trimID: Int
}
var trimArray: [trimObject] = []
override func viewDidLoad() {
super.viewDidLoad()
trimArray.append(trimObject(trimName: "Chrome", trimButton: "chrome-swatch", trimID: 0))
trimArray.append(trimObject(trimName: "Gold", trimButton: "gold-swatch", trimID: 1))
trimArray.append(trimObject(trimName: "Gun Metal", trimButton: "gunmetal-swatch", trimID: 2))
trimSelector.delegate = self
trimSelector.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return trimArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! trimSelectionCell
//Set the label text
cell.trimLabel.text = trimArray[indexPath.item].trimName
//Set the image for the button
cell.trimButton.setImage(UIImage(named: trimArray[indexPath.item].trimButton), for: UIControlState.normal)
//Sets a target function for the button
cell.trimButton.addTarget(self, action: #selector(selectedSwatch), for: .touchUpInside)
return cell
}
func selectedSwatch(sender: UIButton) {
//These set the "selected" border to the button you clicked on.
sender.layer.borderWidth = 2
sender.layer.borderColor = UIColor(red: 83/255, green: 71/255, blue: 65/255, alpha: 1.00).cgColor
}
}
Can anybody please tell me how to access the other buttons in my "selectedSwatch" function?
There are various ways you can handle this. A UICollectionView view has a method visibleCells() that returns an array of it's visible cells. You could use that to get pointers to your cells. You would need a way to figure out which one is which. You could use indexPath(for: UICollectionViewCell) to figure out the index path of each cell, for example.
I don't know if this might help, but what about if you store the IndexPath on your struct on cellForItemAt method?
You will have:
struct trimObject {
var trimName: String
var trimButton: String
var trimID: Int
var idx : IndexPath
}
Then on:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! trimSelectionCell
....
trimArray[indexPath.item].idx = indexPath
....
}
And in your selectedSwatch method:
func selectedSwatch(sender: UIButton) {
//These set the "selected" border to the button you clicked on.
sender.layer.borderWidth = 2
sender.layer.borderColor = UIColor(red: 83/255, green: 71/255, blue: 65/255, alpha: 1.00).cgColor
if let cell = (sender.superview as? UICollectionViewCell) {
//Cell with the button selected:
let idx = collectionView.indexPath(for: cell)
//array of the other objects:
let allOtherObjects = trimArray.filter { ($0 as! trimObject).idx != idx }
allOtherObject.forEach({ (trimObj) in
let cell = collection.cellForItem(at: trimObj.idx)
//Do whatever yo need to do...
//cell.trimButton.layer
})
}
}
Its may be to late but still useful for somebody
Swift 4 version:
You can use sender superview as UiCollectionViewCell
* Consider hierarchy of sender in collection view cell
func selectedSwatch(sender: UIButton) {
let cell = sender.superview?.superview as! trimSelectionCell
//cell.yourbtn
}
Try this,
class trimSelectorVC: UIViewController, UICollectionViewDelegate,
UICollectionViewDataSource {
#IBOutlet weak var trimSelector: UICollectionView!
struct trimObject {
var trimName: String
var trimButton: String
var trimID: Int
var isSelected : String
}
var trimArray: [trimObject] = []
override func viewDidLoad() {
super.viewDidLoad()
trimArray.append(trimObject(trimName: "Chrome", trimButton: "chrome-swatch", trimID: 0,isSelected : "0"))
trimArray.append(trimObject(trimName: "Gold", trimButton: "gold-swatch", trimID: 1,isSelected : "0"))
trimArray.append(trimObject(trimName: "Gun Metal", trimButton: "gunmetal-swatch", trimID: 2,isSelected : "0"))
trimSelector.delegate = self
trimSelector.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return trimArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! trimSelectionCell
//Set the label text
cell.trimLabel.text = trimArray[indexPath.item].trimName
//Set the image for the button
cell.trimButton.setImage(UIImage(named:
trimArray[indexPath.item].trimButton), for: UIControlState.normal)
if(trimArray[indexPath.item].isSelected == "0"){
// button not clicked
// change shadow color of button
}
else
{
// button clicked
cell.trimButton.layer.borderWidth = 2
cell.trimButton.layer.borderColor = UIColor(red: 83/255, green:
71/255,blue: 65/255, alpha: 1.00).cgColor
}
// set tag to the button
cell.trimButton.tag = indexPath.item
//Sets a target function for the button
cell.trimButton.addTarget(self, action:#selector(selectedSwatch),
for: .touchUpInside)
return cell
}
func selectedSwatch(sender: UIButton) {
//These set the "selected" border to the button you clicked on.
let index = sender.tag
for obj in trimArray {
obj.isSelected = "0"
}
trimArray[index].isSelected = "1"
collectionView.reloadData()
}
}

Resources