Home > Back-end >  Call UIButton from String Programmatically
Call UIButton from String Programmatically

Time:06-19

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!
    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 collectionView == firstCV {
            return firstData.count
        }
        
        
        return secondData.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        
        if collectionView == firstCV {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "firstCell", for: indexPath) as! FirstCollectionViewCell
            cell.buttonOne.setTitle(firstData[indexPath.item], for: [])
            return cell
            
            
        }
        
        
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "secondCell", for: indexPath) as! SecondCollectionViewCell
        cell.buttonTwo.setTitle(secondData[indexPath.item], for: [])
        return cell
        
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
        if collectionView == firstCV {
            print("Selected Item: \(indexPath.item) in First CV")
            
            return
        }
        
        print("Selected Item: \(indexPath.item) in Second CV")
        
        
        
    }
    
}

    

CodePudding user response:

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.

CodePudding user response:

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.

CodePudding user response:

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

  • Related