以编程方式使用一个函数触发多个按钮 swift

Multiple buttons triggered with one function programmaticaly swift

试图总结我的代码。问题是我收到 "newCalculator[2861:53607] -[UIButton buttonClicked:]: unrecognized selector sent to instance 0x7fd912651e50" 错误并试图了解我需要做什么?我研究了一些改变选择器语法的解决方案,但这个问题仍然存在。我想要的是;在堆栈视图中,我添加了多个带有顺序的按钮,所有按钮在被单击时都应调用相同的函数。

   o//
//  ViewController.swift
//  newCalculator
//
//  Created by taylank on 17.10.2019.
//  Copyright © 2019 TKT. All rights reserved.
//

import UIKit
var stackViews = [UIStackView]()
class ViewController: UIViewController {


    override func viewDidLoad() {
        super.viewDidLoad()

        //Layer 1
        let containerStackView1 = UIStackView()
        containerStackView1.translatesAutoresizingMaskIntoConstraints = false
        containerStackView1.axis = .vertical
        containerStackView1.distribution = .fillEqually
        containerStackView1.spacing = 1

        //Layer 2
        let topHalfView2 = UIView()
        topHalfView2.translatesAutoresizingMaskIntoConstraints = false
        topHalfView2.backgroundColor = .white
        let botHalfView2 = UIView()
        botHalfView2.translatesAutoresizingMaskIntoConstraints = false


        //Layer 3
        let topLabel3 = UILabel()
        topLabel3.translatesAutoresizingMaskIntoConstraints = false
        topLabel3.text = "0"
        topLabel3.font = UIFont.boldSystemFont(ofSize: 40)

        let containerStackView3 = UIStackView()
        containerStackView3.translatesAutoresizingMaskIntoConstraints = false
        containerStackView3.axis = .vertical
        containerStackView3.distribution = .fillEqually
        containerStackView3.spacing = 1

        //Layer 4
        stackViews = createStackViews(from: 0, to: 4, align: "h")
        let yamaView = UIView()
        yamaView.translatesAutoresizingMaskIntoConstraints = false
        yamaView.backgroundColor = .black

        //ADDING VIEWS TO SCENE .VIEW->Contstckview1->Top-BotHalfView->contstckview2-ResultLabel->horzstackviews
        containerStackView1.addArrangedSubview(topHalfView2)
        containerStackView1.addArrangedSubview(botHalfView2)
        view.addSubview(containerStackView1)
        topHalfView2.addSubview(topLabel3)
        botHalfView2.addSubview(containerStackView3)

        containerStackView3.addArrangedSubview(stackViews[0])
        view.addSubview(yamaView)

        //stackViews[0].topAnchor.constraint(equalTo: containerStackView3.topAnchor, constant: 0).isActive = true

        for a in 1...stackViews.count-1{
              containerStackView3.addArrangedSubview(stackViews[a])

           // stackViews[a].leadingAnchor.constraint(equalTo: stackViews[0].leadingAnchor, constant: 0).isActive = true
            // stackViews[a].trailingAnchor.constraint(equalTo: stackViews[0].trailingAnchor, constant: 0).isActive = true



            }
        //stackViews[0].leadingAnchor.constraint(equalTo: containerStackView3.leadingAnchor, constant: 0).isActive = true
      //  stackViews[0].trailingAnchor.constraint(equalTo: containerStackView3.trailingAnchor, constant: 0).isActive = true

        //Uiheight--v:?--uibottom--uifillequ

        //ConstraintsStackView1
        containerStackView1.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
        containerStackView1.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
        containerStackView1.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
        containerStackView1.heightAnchor.constraint(equalToConstant: view.frame.height).isActive = true

        //TopHalfView2
        topHalfView2.topAnchor.constraint(equalTo: containerStackView1.topAnchor, constant: 0).isActive = true
        topHalfView2.leadingAnchor.constraint(equalTo: containerStackView1.leadingAnchor, constant: 0).isActive = true
        topHalfView2.trailingAnchor.constraint(equalTo: containerStackView1.trailingAnchor, constant: 0).isActive = true
       // topHalfView2.heightAnchor.constraint(equalToConstant: containerStackView1.frame.height/2).isActive = true
        //creates problem conflicts with other constraint fill equally?


        //BotHalfView2
        botHalfView2.bottomAnchor.constraint(equalTo: containerStackView1.bottomAnchor, constant: 0).isActive = true
        botHalfView2.leadingAnchor.constraint(equalTo: containerStackView1.leadingAnchor, constant: 0).isActive = true
        botHalfView2.trailingAnchor.constraint(equalTo: containerStackView1.trailingAnchor, constant: 0).isActive = true
       // botHalfView2.heightAnchor.constraint(equalToConstant: containerStackView1.frame.height/2).isActive = true

         //topLabel3
        topLabel3.bottomAnchor.constraint(equalTo: topHalfView2.bottomAnchor, constant: 0).isActive = true
        topLabel3.trailingAnchor.constraint(equalTo: topHalfView2.trailingAnchor, constant: -5).isActive = true

        //ConstraintsStackView3
            containerStackView3.leadingAnchor.constraint(equalTo: botHalfView2.leadingAnchor, constant: 0).isActive = true
            containerStackView3.trailingAnchor.constraint(equalTo: botHalfView2.trailingAnchor, constant: 0).isActive = true
            containerStackView3.topAnchor.constraint(equalTo: botHalfView2.topAnchor, constant: 0).isActive = true
            containerStackView3.bottomAnchor.constraint(equalTo: botHalfView2.bottomAnchor, constant: 0).isActive = true


        //constraint button

       stackViews[4].arrangedSubviews[2].widthAnchor.constraint(equalTo: stackViews[4].arrangedSubviews[1].widthAnchor,multiplier: 1).isActive = true //sonbutton bir yandakine
        stackViews[4].arrangedSubviews[1].widthAnchor.constraint(equalTo: stackViews[4].arrangedSubviews[0].widthAnchor,multiplier: 0.5).isActive = true // ortadaki buton en soldakine

        yamaView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        yamaView.topAnchor.constraint(equalTo: stackViews[4].bottomAnchor).isActive = true
        yamaView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
       yamaView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true


    }


}
func createButtons(_ named: String...)->[UIButton]{
    var c = 0
return named.map { name in

        let button = UIButton()
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitle(name, for: .normal)
        button.backgroundColor = UIColor.gray
        button.setTitleColor(.white, for: .normal)
        button.layer.cornerRadius = 1
       button.addTarget(button, action: #selector(buttonClicked) ,for:.touchUpInside)


        return button


}



}
@objc func buttonClicked(_ sender:UIButton){

      print("clicked")
  }

func createStackViews(from x: Int,to y:Int, align type: String)->[UIStackView]{
    // use tag instead of name---
    //use dictionary..keys name values



    if (type == "v"){


        for a in x...y{

            let stackVertical = UIStackView()
                stackVertical.translatesAutoresizingMaskIntoConstraints = false
                stackVertical.axis = .vertical
                stackVertical.spacing = 1
                stackVertical.distribution = .fillEqually
                stackVertical.tag = a

        }





    }
    else if(type=="h"){
        var counter = 0
        for a in x...y{
                    counter += 1

                    switch counter{
                    case 1: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("Clear","+/-","%","÷"))

                    stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
                    stackHorizontal.axis = .horizontal
                    stackHorizontal.spacing = 1
                    stackHorizontal.distribution = .fillEqually
                    stackHorizontal.tag = 90+a
                    stackViews.append(stackHorizontal)

                    case 2: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("7","8","9","x"))

                    stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
                    stackHorizontal.axis = .horizontal
                    stackHorizontal.spacing = 1
                    stackHorizontal.distribution = .fillEqually
                    stackHorizontal.tag = 100 + a
                    stackViews.append(stackHorizontal)

                    case 3: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("4","5","6","-"))

                    stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
                    stackHorizontal.axis = .horizontal
                    stackHorizontal.spacing = 1
                    stackHorizontal.distribution = .fillEqually
                    stackHorizontal.tag = 110+a
                    stackViews.append(stackHorizontal)

                    case 4: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("1","2","3","+"))

                     stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
                     stackHorizontal.axis = .horizontal
                     stackHorizontal.spacing = 1
                     stackHorizontal.distribution = .fillEqually
                     stackHorizontal.tag = 120 + a
                     stackViews.append(stackHorizontal)

                    case 5: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("0",",","="))

                     stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
                     stackHorizontal.axis = .horizontal
                     stackHorizontal.spacing = 1
                    stackHorizontal.distribution = .fillProportionally
                     stackHorizontal.tag = 130 + a
                     stackViews.append(stackHorizontal)
                    default:
                        break
            }

             }


        return stackViews
    }



    return [UIStackView.init()]
 }

------------解决方案------------

所有函数都在viewcontrollerclass

里面
    class ViewController: UIViewController {

    override func viewDidLoad() {
     stackViews = createStackViews(from: 0, to: 4, align: "h")
    }

     func createButtons(_ named: String...)->[UIButton]{
//codes
              button.addTarget(self, action: #selector(buttonClicked) ,for:.touchUpInside)
//codes
     }
     @objc func buttonClicked(_ sender:UIButton){

                 print("clicked")
             }


    func createStackViews(from x: Int,to y:Int, align type: String)->[UIStackView]{
//codes
    UIStackView(arrangedSubviews:createButtons("Clear","+/-","%","÷"))
    //codes
               }

    }

替换

button.addTarget(button, action: "buttonClicked:" ,for:.touchUpInside)

button.addTarget(self, action: #selector(buttonClicked) ,for:.touchUpInside)

@objc func buttonClicked(_ sender:UIButton){

import UIKit
var stackViews = [UIStackView]()
class ViewController: UIViewController {


    override func viewDidLoad() {
        super.viewDidLoad()

        //Layer 1
        let containerStackView1 = UIStackView()
        containerStackView1.translatesAutoresizingMaskIntoConstraints = false
        containerStackView1.axis = .vertical
        containerStackView1.distribution = .fillEqually
        containerStackView1.spacing = 1

        //Layer 2
        let topHalfView2 = UIView()
        topHalfView2.translatesAutoresizingMaskIntoConstraints = false
        topHalfView2.backgroundColor = .white
        let botHalfView2 = UIView()
        botHalfView2.translatesAutoresizingMaskIntoConstraints = false


        //Layer 3
        let topLabel3 = UILabel()
        topLabel3.translatesAutoresizingMaskIntoConstraints = false
        topLabel3.text = "0"
        topLabel3.font = UIFont.boldSystemFont(ofSize: 40)

        let containerStackView3 = UIStackView()
        containerStackView3.translatesAutoresizingMaskIntoConstraints = false
        containerStackView3.axis = .vertical
        containerStackView3.distribution = .fillEqually
        containerStackView3.spacing = 1

        //Layer 4
        stackViews = createStackViews(from: 0, to: 4, align: "h")
        let yamaView = UIView()
        yamaView.translatesAutoresizingMaskIntoConstraints = false
        yamaView.backgroundColor = .black

        //ADDING VIEWS TO SCENE .VIEW->Contstckview1->Top-BotHalfView->contstckview2-ResultLabel->horzstackviews
        containerStackView1.addArrangedSubview(topHalfView2)
        containerStackView1.addArrangedSubview(botHalfView2)
        view.addSubview(containerStackView1)
        topHalfView2.addSubview(topLabel3)
        botHalfView2.addSubview(containerStackView3)

        containerStackView3.addArrangedSubview(stackViews[0])
        view.addSubview(yamaView)

        //stackViews[0].topAnchor.constraint(equalTo: containerStackView3.topAnchor, constant: 0).isActive = true

        for a in 1...stackViews.count-1{
              containerStackView3.addArrangedSubview(stackViews[a])

           // stackViews[a].leadingAnchor.constraint(equalTo: stackViews[0].leadingAnchor, constant: 0).isActive = true
            // stackViews[a].trailingAnchor.constraint(equalTo: stackViews[0].trailingAnchor, constant: 0).isActive = true



            }
        //stackViews[0].leadingAnchor.constraint(equalTo: containerStackView3.leadingAnchor, constant: 0).isActive = true
      //  stackViews[0].trailingAnchor.constraint(equalTo: containerStackView3.trailingAnchor, constant: 0).isActive = true

        //Uiheight--v:?--uibottom--uifillequ

        //ConstraintsStackView1
        containerStackView1.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
        containerStackView1.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
        containerStackView1.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
        containerStackView1.heightAnchor.constraint(equalToConstant: view.frame.height).isActive = true

        //TopHalfView2
        topHalfView2.topAnchor.constraint(equalTo: containerStackView1.topAnchor, constant: 0).isActive = true
        topHalfView2.leadingAnchor.constraint(equalTo: containerStackView1.leadingAnchor, constant: 0).isActive = true
        topHalfView2.trailingAnchor.constraint(equalTo: containerStackView1.trailingAnchor, constant: 0).isActive = true
       // topHalfView2.heightAnchor.constraint(equalToConstant: containerStackView1.frame.height/2).isActive = true
        //creates problem conflicts with other constraint fill equally?


        //BotHalfView2
        botHalfView2.bottomAnchor.constraint(equalTo: containerStackView1.bottomAnchor, constant: 0).isActive = true
        botHalfView2.leadingAnchor.constraint(equalTo: containerStackView1.leadingAnchor, constant: 0).isActive = true
        botHalfView2.trailingAnchor.constraint(equalTo: containerStackView1.trailingAnchor, constant: 0).isActive = true
       // botHalfView2.heightAnchor.constraint(equalToConstant: containerStackView1.frame.height/2).isActive = true

         //topLabel3
        topLabel3.bottomAnchor.constraint(equalTo: topHalfView2.bottomAnchor, constant: 0).isActive = true
        topLabel3.trailingAnchor.constraint(equalTo: topHalfView2.trailingAnchor, constant: -5).isActive = true

        //ConstraintsStackView3
            containerStackView3.leadingAnchor.constraint(equalTo: botHalfView2.leadingAnchor, constant: 0).isActive = true
            containerStackView3.trailingAnchor.constraint(equalTo: botHalfView2.trailingAnchor, constant: 0).isActive = true
            containerStackView3.topAnchor.constraint(equalTo: botHalfView2.topAnchor, constant: 0).isActive = true
            containerStackView3.bottomAnchor.constraint(equalTo: botHalfView2.bottomAnchor, constant: 0).isActive = true


        //constraint button

       stackViews[4].arrangedSubviews[2].widthAnchor.constraint(equalTo: stackViews[4].arrangedSubviews[1].widthAnchor,multiplier: 1).isActive = true //sonbutton bir yandakine
        stackViews[4].arrangedSubviews[1].widthAnchor.constraint(equalTo: stackViews[4].arrangedSubviews[0].widthAnchor,multiplier: 0.5).isActive = true // ortadaki buton en soldakine

        yamaView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        yamaView.topAnchor.constraint(equalTo: stackViews[4].bottomAnchor).isActive = true
        yamaView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
       yamaView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true


    }



func createButtons(_ named: String...)->[UIButton]{
    var c = 0
return named.map { name in

        let button = UIButton()
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitle(name, for: .normal)
        button.backgroundColor = UIColor.gray
        button.setTitleColor(.white, for: .normal)
        button.layer.cornerRadius = 1
       button.addTarget(self, action: #selector(buttonClicked) ,for:.touchUpInside)


        return button


}



}
@objc func buttonClicked(_ sender:UIButton){

      print("clicked")
  }

func createStackViews(from x: Int,to y:Int, align type: String)->[UIStackView]{
    // use tag instead of name---
    //use dictionary..keys name values



    if (type == "v"){


        for a in x...y{

            let stackVertical = UIStackView()
                stackVertical.translatesAutoresizingMaskIntoConstraints = false
                stackVertical.axis = .vertical
                stackVertical.spacing = 1
                stackVertical.distribution = .fillEqually
                stackVertical.tag = a

        }





    }
    else if(type=="h"){
        var counter = 0
        for a in x...y{
                    counter += 1

                    switch counter{
                    case 1: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("Clear","+/-","%","÷"))

                    stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
                    stackHorizontal.axis = .horizontal
                    stackHorizontal.spacing = 1
                    stackHorizontal.distribution = .fillEqually
                    stackHorizontal.tag = 90+a
                    stackViews.append(stackHorizontal)

                    case 2: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("7","8","9","x"))

                    stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
                    stackHorizontal.axis = .horizontal
                    stackHorizontal.spacing = 1
                    stackHorizontal.distribution = .fillEqually
                    stackHorizontal.tag = 100 + a
                    stackViews.append(stackHorizontal)

                    case 3: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("4","5","6","-"))

                    stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
                    stackHorizontal.axis = .horizontal
                    stackHorizontal.spacing = 1
                    stackHorizontal.distribution = .fillEqually
                    stackHorizontal.tag = 110+a
                    stackViews.append(stackHorizontal)

                    case 4: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("1","2","3","+"))

                     stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
                     stackHorizontal.axis = .horizontal
                     stackHorizontal.spacing = 1
                     stackHorizontal.distribution = .fillEqually
                     stackHorizontal.tag = 120 + a
                     stackViews.append(stackHorizontal)

                    case 5: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("0",",","="))

                     stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
                     stackHorizontal.axis = .horizontal
                     stackHorizontal.spacing = 1
                    stackHorizontal.distribution = .fillProportionally
                     stackHorizontal.tag = 130 + a
                     stackViews.append(stackHorizontal)
                    default:
                        break
            }

             }


        return stackViews
    }



    return [UIStackView.init()]
 }


 }

你有几个问题:

您的选择器需要 selector(buttonClicked(:)),所以

button.addTarget(self, action: #selector(buttonClicked(:)) ,for:.touchUpInside)

你的函数 buttonClicked(_:)createButtons() 需要在你的视图控制器中 class。事实上,buttonClicked(_:) 是一个全局函数,这意味着它不能成为 target/action 的一部分。 (动作方法需要在目标对象中(通常是拥有按钮的视图控制器。)