skip to Main Content

This is my code for my CollectionViews. I have two CollectionViews so far, and as you can see in the Strings in the code, they each have 6 buttons. I need to call the buttons from the Strings so that when they are pressed, a new window opens. The new window will contain things like flashcards, pertaining to the subject of the button that was pressed.

For reference, here is what the simulator looks like.

code:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }


}

class FirstCollectionViewCell: UICollectionViewCell {
    
    @IBOutlet weak var buttonOne: UIButton!
    
    override func awakeFromNib() {
        super.awakeFromNib()
        commonInit()
    }
    func commonInit() {
        guard buttonOne != nil else { return }
        buttonOne.titleLabel!.font = UIFont(name: "Marker Felt", size: 20)
        buttonOne.layer.cornerRadius = 10
        buttonOne.clipsToBounds = true
        buttonOne.layer.borderWidth = 1.0
        buttonOne.layer.borderColor = UIColor.white.cgColor
        }
    }

class SecondCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var buttonTwo: UIButton!
    override func awakeFromNib() {
        super.awakeFromNib()
        commonInit()
    }
    func commonInit() {
        guard buttonTwo != nil else { return }
        buttonTwo.titleLabel!.font = UIFont(name: "Marker Felt", size: 20)
        buttonTwo.layer.cornerRadius = 10
        buttonTwo.clipsToBounds = true
        buttonTwo.layer.borderWidth = 1.0
        buttonTwo.layer.borderColor = UIColor.white.cgColor
    }
}

class TwoCollectionsViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
    @IBOutlet weak var firstCV: UICollectionView!
    @IBOutlet weak var secondCV: UICollectionView!
    
    @IBAction func Buttons(_ sender: Any) {
        if let btn = sender as? UIButton {
            print(btn.restorationIdentifier!)
                guard let button = sender as? UIButton else { return }
                guard let id = Int(button.restorationIdentifier!) else {return}
                if id < firstData.count {
                 performSegue(withIdentifier: "Good Work", sender: btn)
                }
                else {
                 performSegue(withIdentifier: "Nice Try", sender: btn)
                }
                print(button.restorationIdentifier!)
               
        }
        
    }
    
    let firstData: [String] = [
        "Good Work", "Nice Try", "Btn 3", "Btn 4", "Btn 5", "Btn 6"
    ]

    let secondData: [String] = [
        "Second 1", "Second 2", "Second 3", "Second 4", "Second 5", "Second 6"
    ]

    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        firstCV.dataSource = self
        firstCV.delegate = self
        
        secondCV.dataSource = self
        secondCV.delegate = self
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // if it's the First Collection View
        if collectionView == firstCV {
            return firstData.count
        }
        
        // it's not the First Collection View, so it's the Second one
        return secondData.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        // if it's the First Collection View
        if collectionView == firstCV {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "firstCell", for: indexPath) as! FirstCollectionViewCell
            cell.buttonOne.setTitle(firstData[indexPath.item], for: []) //allows for button title change in code above
           cell.buttonOne.restorationIdentifier = "(indexPath.row + firstData.count)"
            return cell
            
            
        }
        
        // it's not the First Collection View, so it's the Second one
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "secondCell", for: indexPath) as! SecondCollectionViewCell
        cell.buttonTwo.setTitle(secondData[indexPath.item], for: [])
        cell.buttonTwo.restorationIdentifier = "(indexPath.row)"
        return cell
        
    }
}

3

Answers


  1. It looks like you only defined @IBOutlet variables for your buttons. Create @IBAction functions and put the code that "open new windows" (i.e. performs segues) in that function.

    There are many resources online explaining how to do that. One of them is this one.

    Login or Signup to reply.
  2. Just in didSelectItemAt write a switch case.

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
        if collectionView == firstCV {
            handleCases(text : firstData[indexPath.item])
        } else {
            handleCases(text : secondData[indexPath.item])
        }
        
    }
    
    func handleCases(text : String) {
        switch text {
            case firstData[0]:
                print("clicked (firstData[0])
                // write here code to go to details
                break
                      
            case firstData[1]:
                print("clicked (firstData[0])
                break
                     
            // put all 6 cases of firstData and secondData and then default
        }
    }
    

    Another solution will be add IBAction inside cell and call handleCases(text : String) inside cell in this IBAction.

    Login or Signup to reply.
  3. I found out it’s better to use @IBAction callback function for the two button’s instead of delegate callback function aka(didSelect)

    first you can create @IBAction in (TwoCollectionsViewController) then link both (buttonOne, buttonTwo) to this func, in the mean time while user pressed a button you can know which button was pressed(depends on your use case), for that setting an id for the buttons is best option,
    you can add this line to both Collection view button(buttonOne, buttonTwo) before returning the cell in(cellForRowAt):
    cell.buttonOne.restorationIdentifier = "(indexPath.row)"

    then add:

    if let btn = sender as? UIButton {
       print(btn.restorationIdentifier)
    }
    

    to the @IBAction func, after that you can use:

    performSegue(withIdentifier: "Your Identifier", sender: btn)
    

    override: prepare(for segue: UIStoryboardSegue, sender: Any?) function
    then you can configure destination View Controller in the (prepare function)

    hopefully this solves your issue 🙂

    update:
    first change the

    cell.buttonTwo.restorationIdentifier = "(indexPath.row)"
    

    inside second if statement (if collectionView == secondCV) to

    cell.buttonTwo.restorationIdentifier = "(indexPath.row + firstData.count)"
    

    then change @IBAction to:

    @IBAction func buttonPressed(_ sender: Any) {
     guard let button = sender as? UIButton else { return }
     guard let id = Int(button.restorationIdentifier!) else {return} 
     if id < firstData.count { 
      performSegue(withIdentifier: "Good Work", sender: btn) 
     } 
     else { 
      performSegue(withIdentifier: "Nice Try", sender: btn) 
     } 
     print(button.restorationIdentifier!)
    }
    

    after that you can override prepare(for segue: UIStoryboardSegue, sender: Any?) for extra modification , inside (class scope) not in @IBAction

    .
    .
    .
    cellForRow:

    • copy and replace your entire content code with this one:

        // if it's the First Collection View
        if collectionView == firstCV {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "firstCell", for: indexPath) as! FirstCollectionViewCell
            cell.buttonOne.setTitle(firstData[indexPath.item], for: []) //allows for button title change in code above
           cell.buttonOne.restorationIdentifier = "(indexPath.row)"
            return cell  
        }
      
        // it's not the First Collection View, so it's the Second one
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "secondCell", for: indexPath) as! SecondCollectionViewCell
        cell.buttonTwo.setTitle(secondData[indexPath.item], for: [])
        cell.buttonTwo.restorationIdentifier = "(indexPath.row + firstData.count)"
        return cell
        }
      
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search