【问题标题】:Multiple buttons triggered with one function programmaticaly swift以编程方式快速使用一个功能触发多个按钮
【发布时间】:2019-10-20 12:38:45
【问题描述】:

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

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

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

所有的函数都在 viewcontroller 类中

    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
               }

    }

【问题讨论】:

    标签: swift uibutton selector uistackview


    【解决方案1】:

    你有几个问题:

    你的选择器必须是selector(buttonClicked(:)),所以

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

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

    【讨论】:

    • 您还应该按照我和 Sh_Khan 的建议进行操作,并将您的 addTarget(_:action:) 方法更改为使用 action: #selector(buttonClicked(:) 表单来指定操作的选择器。您使用action: "buttonClicked:" 的代码将操作指定为字符串,编译器无法验证这种方法是否存在。这就是你崩溃的原因。 (您的目标对象不包含指定的方法。)如果您使用#selector() 语法来指定操作的选择器,编译器可以验证您有一个与选择器签名匹配的方法。
    • 我上面评论中的动作位应该是action: #selector(buttonClicked(_:)。我错过了匿名参数的下划线。
    【解决方案2】:

    替换

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

    【讨论】:

    • 问题是;也不能使用 self(未解析的标识符) '#selector' 的参数不能引用全局函数 'buttonClicked',最后一个是 objc 只能与类的成员、objc 协议和类的具体扩展一起使用。我想我错过了一些东西。我的函数不在 viewcontroller 类 createStacksViews 内,而 createButtons 在类外。
    • 请分享它存在的地方?
    猜你喜欢
    • 1970-01-01
    • 2020-09-23
    • 1970-01-01
    • 1970-01-01
    • 2016-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多