-2

I've added buttons into uistackview programmatically with for loop but I want each button have it's own separate listeners and I can't think up a logic for it. I've tried to add a #selector but obviously they all call the same method.

    for imageName in imagesArray1{
        let imageButton: UIButton = {
            let button = UIButton()
            let myUIImage = UIImage(named: imageName as! String)
            button.setImage(myUIImage, for: .normal)
            button.contentMode = .scaleAspectFit
            button.tag = buttonTag
            buttonTag += 1
            button.addTarget(self, action: #selector(handleSelectedAvatar(_:)), for:.touchUpInside)
            button.translatesAutoresizingMaskIntoConstraints = false
            return button
        }()
        stackView1.addArrangedSubview(imageButton)
        imageButton.widthAnchor.constraint(equalTo: stackView1.widthAnchor, multiplier: 1/4).isActive = true
        imageButton.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.width/4).isActive = true
    }
Mumtaz Hussain
  • 925
  • 9
  • 23
  • 1
    Please don't post pictures of code or other text. Copy and paste the code into your question as text. – rmaddy Oct 17 '18 at 06:31
  • I've tried but it kept bugging me with indent error, tried for fix every indent issue but still it didn't let me post the question so finally I uploaded a pic. But I can understand your concern, thanks for the tip. – Mumtaz Hussain Oct 17 '18 at 06:32
  • Did you try use array of selectors with selector for each button? – Nikdemm Oct 17 '18 at 06:32
  • @Nikdemm I haven't it's a good idea but It'll make me create 16 different listeners, is there any way if I can just pass the imageName into the arguments and when I click on a button it only passes that selected imageName into that selector arguments? This way only 1 listener would work differently for all buttons. – Mumtaz Hussain Oct 17 '18 at 06:37

2 Answers2

2

There are 2 solutions.

1) Use single selector for all buttons:

button.tag = some_tag (Int)
button.addTarget(self, action: #selector(handleSelectedAvatar(_:)), for: .touchupInside)

handleSelectedAvatar implementation:

@objc func handleSelectedAvatar(_ sender: UIButton) {
    switch sender.tag {
    case 0: // Do something with UIButton with tag 0
    case ...
    }
}

2) Use array of selectors:

let selectors = [#selector(handleSelectedAvatar), ...]

Than set selectors for buttons:

button.addTarget(self, action: selectors[your_index], for: .touchupInside)
Ilya Kharabet
  • 4,203
  • 3
  • 15
  • 29
2

First of all, you should edit your question, just post the code and I'll edit it for you if you find it hard to indent or format it properly.

There are multiple ways I can think of to do what you wanna do. The easiest is to use the tag property of a button. This tag should help you out to access any object (or UIImage in your case) from your array of images. Assign the tag based on the current index of your loop, then each button would have a common selector method.

import UIKit

class ViewController: UIViewController {

    internal lazy var stackView: UIStackView = {
        let stackView = UIStackView(arrangedSubviews: [])
        stackView.axis = .vertical
        stackView.alignment = .fill
        stackView.distribution = .fillEqually
        stackView.spacing = 10
        return stackView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.backgroundColor = .white

        // StackView Autolayout

        self.view.addSubview(self.stackView)
        self.stackView.translatesAutoresizingMaskIntoConstraints = false

        self.view.addConstraint(NSLayoutConstraint(item: self.stackView, attribute: .top, relatedBy: .equal, toItem: self.view, attribute: .top, multiplier: 1.0, constant: 100.0))
        self.view.addConstraint(NSLayoutConstraint(item: self.stackView, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1.0, constant: 20.0))
        self.view.addConstraint(NSLayoutConstraint(item: self.stackView, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1.0, constant: 20.0))

        // Add Buttons

        for index in 1...10 {
            let button = UIButton(type: .custom)
            button.backgroundColor = UIColor.gray
            button.setTitle("Button #\(index)", for: .normal)
            button.addTarget(self, action: #selector(self.buttonHandler(_:)), for: .touchUpInside)
            button.tag = index
            self.stackView.addArrangedSubview(button)
        }
    }

    @objc private func buttonHandler(_ button: UIButton) {
        print("Tapped button #:\(button.tag)")
    }
}

I hope this helps!

Glenn Posadas
  • 12,555
  • 6
  • 54
  • 95