Passing data from custom UI cell to view controller - ios

I am creating a pokedex app and the way I want it to work is basically there is a scroller at the top of the screen which allows you to select any pokemon and upon choosing the pokemon, underneath the scroller the entry for the pokemon will show up (bulbasaur will be there by default until a pokemon is selected because bulbasaur is the first pokemon with an ID of 1). To achieve this I have my view controller return two types of cells, the first being a "chooser cell" which is the scroller, and the second being a "description cell" which is the dex entry. I gave the view controller a data member called dex entry and return dex entry in the cellForItemAt function but the image of the cell is not changing (from bulbasaur to whichever pokemon I select). I print to the console what is the value of dex entry's pokemon every time a pokemon is selected so I am sure that the dex entry is being directly changed but I don't know why the image is not changing as well. Below are relevant parts of my code.
view controller (only part of it):
import UIKit
class PokeDexController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var dexEntry = DescriptionCell()
override func viewDidLoad() {
super.viewDidLoad()
self.title = "PokeDex 386"
collectionView?.backgroundColor = UIColor(red: 52/255.0, green: 55/255.0, blue: 64/255.0, alpha: 1.0)
//collectionView?.backgroundColor = UIColor.white
collectionView?.register(chooserCell.self, forCellWithReuseIdentifier: cellID)
collectionView?.register(DescriptionCell.self, forCellWithReuseIdentifier: descID)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if (indexPath.row == 0)
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellID, for: indexPath) as! chooserCell
return cell
}
else{
let descCell = collectionView.dequeueReusableCell(withReuseIdentifier: descID, for: indexPath) as! DescriptionCell
dexEntry = descCell
return dexEntry
}
}
descriptionCell class:
import UIKit
class DescriptionCell: UICollectionViewCell
{
private var pokemon : Pokemon?
{
didSet
{
if let id = pokemon?._id
{
imageView.image = UIImage(named: String(id))
print("Pokemon with the id of " + String(id))
}
}
}
override init(frame: CGRect)
{
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setPokemon(poke: Pokemon)
{
self.pokemon = poke
}
func getPokemon() -> Pokemon
{
return pokemon!
}
let imageView: UIImageView =
{
let iv = UIImageView()
iv.image = UIImage(named: "1")
iv.contentMode = .scaleAspectFill
return iv
}()
func setupViews()
{
backgroundColor = UIColor(red: 52/255.0, green: 55/255.0, blue: 64/255.0, alpha: 1.0)
addSubview(imageView)
imageView.frame = (CGRect(x: frame.width/6, y: frame.height/30, width: frame.width/4, height: frame.height/4))
}
}
choosercell class (specifically the didSelectItemAt):
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath){
let poke = pokemon[indexPath.row]
print("Selected " + poke._name)
let vc = PokeDexController()
vc.dexEntry.setPokemon(poke: poke)
let name = vc.dexEntry.getPokemon()._name
print(name ?? "nothing there")
}
image of the app and the console output
any help is appreciated, thanks.

You need to change the dexEntry when you select a cell and reload the collection view cell.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath){
let poke = pokemon[indexPath.row]
print("Selected " + poke._name)
let cell = collectionView.cellForItem(at: IndexPath(row: 1, section: 0) as! DescriptionCell
cell.setPokemon(poke: poke)
collectionView.reloadItems(at: IndexPath(row: 1, section: 0))
}
Hope this helps.

I haven't solved my problem but I realize that the cell that I am returning in my viewController is independent of dexEntry so as far as I can cell, once that cell is set, it is set, so I now i will figure out how to reload things when a cell is selected so the cell that is returned has an image of a different pokemon.

Related

Collection View Cell Action using Delegates and Protocols

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

UICollectionView didSelectItemAt never triggers

In my VC I have a view that pulls up from the bottom. I setup and add a UICollectionView in the viewDidLoad():
//Add and setup the collectionView
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: flowLayout)
collectionView?.register(PhotoCell.self, forCellWithReuseIdentifier: "photoCell")
collectionView?.delegate = self
collectionView?.dataSource = self
collectionView?.backgroundColor = #colorLiteral(red: 0.9771530032, green: 0.7062081099, blue: 0.1748393774, alpha: 1)
collectionView?.allowsMultipleSelection = false
collectionView?.allowsSelection = true
pullUpView.addSubview(collectionView!)
pullUpView.bringSubview(toFront: collectionView!)
The UICollectionView Delegate methods are in an extension, for now in the same codefile as the VC:
//MARK: - Extension CollectionView
extension MapVC: UICollectionViewDelegate, UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imagesArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCell", for: indexPath) as? PhotoCell {
let imageFromIndex = imagesArray[indexPath.item]
let imageView = UIImageView(image: imageFromIndex )
cell.addSubview(imageView)
return cell
} else {
return PhotoCell()
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("selected")
//Create PopVC instance, using storyboard id set in storyboard
guard let popVC = storyboard?.instantiateViewController(withIdentifier: "popVC") as? PopVC else { return }
popVC.passedImage = imagesArray[indexPath.row]
present(popVC, animated: true, completion: nil)
}
}
The problem is that when I tap on a cell nothing happens. I've put a print statement inside the didSelectItemAt method, but that never gets printed. So, my cells never get selected or at least the didSelectItemAt method never gets triggered!
Been debugging and trying for hours, and I can't see what's wrong. Any help appreciated. Perhaps someone could open mijn project from Github to see what's wrong, if that is allowed ?
UPDATE:
Using Debug View Hierarchy, I see something disturbing: Each photoCell has multiple (many!) UIImageViews. I think that should be just one UIImageView per photoCell. I don't know what is causing this behaviour?
Debug View Hierarchy
I checked your code, there are few problems:
First of all you have to change your PhotoCell implementation, and add your imageView inside the class, only when the cell is created. Your cell is not loading a XIB so you have to add the imageView in init(frame:):
class PhotoCell: UICollectionViewCell {
var photoImageView: UIImageView!
override init(frame: CGRect) {
super.init(frame: frame)
setupCell()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupCell() {
photoImageView = UIImageView()
addSubview(photoImageView)
}
override func layoutSubviews() {
super.layoutSubviews()
photoImageView.frame = bounds // ensure that imageView size is the same of the cell itself
}
}
After this change, in cellForItem method you can do cell.photoImageView.image = imageFromIndex.
The problem of didSelect not called is caused by the fact your pullUpViewis always with height = 1, even if you're able to see the collectionView, it will not receive any touch.
First add an IBOutlet of the height constraint of pullUpView in your MapVc
When creating collection view, ensure the size of collection view is the same of the pullUpView, so it will be able to scroll; collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: 300), collectionViewLayout: flowLayout)
Then change animateViewUp and animateViewDown to this
func animateViewUp() {
mapViewBottomConstraint.constant = 300
pullUpViewHeightConstraint.constant = 300 // this will increase the height of pullUpView
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
}
#objc func animateViewDown() {
cancelAllSessions()
//remove previous loaded images and urls
imagesArray.removeAll()
imageUrlsArray.removeAll()
mapViewBottomConstraint.constant = 0
pullUpViewHeightConstraint.constant = 0 // this will reset height to 0
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
}
By doing all of this the swipe down gesture will not work anymore because the touch is intercepted and handled by the collection view, you should handle this manually.
However I suggest you to change the online course, there are a lot of things that I don't like about this code.

Found nil while setting value of a label inside Collection view cell

Case:
I'm using a collection view inside a UIView, I've connected it as an outlet called 'partsCollectionView'. I've created a cell with identifier 'cell' and a custom class 'SelectionCollectionViewCell' for that cell. Inside the cell, I've got a label called 'cellTitle'.
Error: Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
I'm facing the error while setting the value of that label inside 'cellForItemAt' Method.
Here are the concerned views:
Cell description,
and, collection View Description
The Cell Class is:
import UIKit
class SelectionCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var cellTitle: UILabel!
}
The class where I'll use the collection view is:
import UIKit
private let reuseIdentifier = "cell"
let array = ["small","Big","Medium","Very big","Toooo big String","small"]
class SelectionCollectionViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
#IBOutlet weak var partsCollectionView: UICollectionView!
#IBOutlet weak var instructionsView: UITextView!
#IBOutlet weak var image: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.partsCollectionView.register(SelectionCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return array.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = partsCollectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! SelectionCollectionViewCell
cell.layer.cornerRadius = 10
cell.clipsToBounds = true
cell.cellTitle.text = array[indexPath.row]
cell.layer.borderColor = #colorLiteral(red: 0.07843137255, green: 0.6862745098, blue: 0.9529411765, alpha: 0.6819349315)
cell.layer.borderWidth = 2
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let name = array[indexPath.row]
let attributedName = NSAttributedString(string: name)
let width = attributedName.widthWithConstrainedHeight(height: 20.0)
return CGSize(width: width + 40, height: 30.0)
}
}
extension NSAttributedString {
func widthWithConstrainedHeight(height: CGFloat) -> CGFloat {
let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, context: nil)
return boundingBox.width
}
}
Update: This is how it looks if I skip setting the title text. The title will come inside those rounded boxes.
Remove this line from viewDidLoad.
self.partsCollectionView.register(SelectionCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
When you register a cell programmatically it creates a new collection view cell object. It doesn't get the cell from storyboard. So cellTitle will be nil
OR
Programmatically initialize the label in custom collection view cell
class SelectionCollectionViewCell:UICollectionViewCell {
let cellTitle = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(cellTitle)
cellTitle.frame = CGRect(x: 10, y: 10, width: 100, height: 30)
}
}
Just minor mistake is there I think, In cellForItemAt indexPath Please update following line,
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! SelectionCollectionViewCell
I just paste your code and got following output, nothing else,
If you still unable to produce desired output, just delete existing UILabel from SelectionCollectionViewCell and add it again.
FYI. No need to register cell in viewDidLoad() method

UICollectionViewController can't reach cell

I tried to change the text of my label inside an UICollectionViewCell. The ViewCell class is linked to the cell, the outlets are set and in the viewController its registered by
// Register cell classes
self.collectionView!.register(ImageCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
and in cellForItemAt...
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! ImageCollectionViewCell
but I can't access the label. Same problem with an imageView. If I tried to set the text with:
cell.hund.text = "bla"
the label "hund" is known but it throws that the label is nil.
Thanks Tom
ImageCollectionVC
import UIKit
private let reuseIdentifier = "cell"
class ImageCollectionVC: UICollectionViewController {
var listOfImages = [Int: KKImage]()
override func viewDidLoad() {
super.viewDidLoad()
// Register cell classes
self.collectionView!.register(ImageCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
listOfImages = xmlParseImageSource()
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return listOfImages.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! ImageCollectionViewCell
let imgUrl = listOfImages[indexPath.row]?.imagePreviewUrl
do {
let bindData = try Data(contentsOf: imgUrl!)
let img = UIImage(data: bindData)
cell.hund.text = "bla"
//cell.img.image = img
//cell.img.image = UIImage(data: bindData)
} catch {
print(error.localizedDescription)
}
cell.backgroundColor = UIColor.blue
return cell
}
}
ImageCollectionViewCell
import UIKit
class ImageCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var img: UIImageView!
#IBOutlet weak var hund: UILabel!
}
Thomas in awake from nib just initialize your UIImageView and UILabel and add them to the cell, it should work :)
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code, you obviously need to set the frames/constraints as per your requirement
img = UIImageView(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
hund = UILabel(frame: CGRect(x: 50, y: 0, width: 300, height: 40))
self.addSubview(img)
self.addSubview(hund)
}
In case you are using an xib don't register the class instead use the nib registration which should be:
self.collectionView.register(UINib.init(nibName: "ImageCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: reuseIdentifier )

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