【问题标题】:Action not being called when button is tapped in a stack view在堆栈视图中点击按钮时未调用操作
【发布时间】:2019-01-08 18:45:24
【问题描述】:

我有一个包含堆栈视图的自定义视图。在堆栈视图中,我有一个标签和一个按钮。

我通过以下方式创建了我的堆栈视图、标签和按钮,并将它们添加到父视图中。

class HomeView: UIView {

override init(frame: CGRect) {
    super.init(frame: frame)
    translatesAutoresizingMaskIntoConstraints = false

    addSubview(stackView)
    stackView.addArrangedSubview(haveAccount)
    stackView.addArrangedSubview(signin)
    stackView.setCustomSpacing(4.0, after: haveAccount)
}

let stackView: UIStackView = {
    let stack = UIStackView()
    stack.translatesAutoresizingMaskIntoConstraints = false
    stack.distribution = .fillProportionally
    stack.alignment = .fill
    stack.isUserInteractionEnabled = false
    return stack
}()

let haveAccount: UILabel = {
    let label = UILabel()
    ...
    return label
}()

let signin: UIButton = {
    let button = UIButton()
    button.translatesAutoresizingMaskIntoConstraints = false
    button.setTitle("Sign in", for: .normal)
    button.titleLabel?.font = UIFont(name: "Avenir", size: 14)
    button.setTitleColor(UIColor.white, for: .normal)
    button.addTarget(self, action: #selector(HomeController.loginClicked(_:)), for: .touchUpInside)
    return button
}()

}

在我的视图控制器中,我将视图添加到控制器的基本视图并设置约束。我还创建了点击登录按钮时应该调用的方法。

override func viewDidLoad() {
    super.viewDidLoad()

    homeView = HomeView()
    homeView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(homeView)
    homeView.fullscreenView(parentView: view)
}

@objc func loginClicked(_ sender: UIButton) {        
    print("sign in button pressed")
}

当我按下按钮时,不会调用 loginClicked 方法。现在我确实尝试将 loginClicked 方法移动到自定义视图并相应地更改 addTarget 并调用 loginClicked 方法。话虽这么说,我知道按钮是可点击的,但我认为按钮操作的目标不正确,这就是未调用视图控制器中的 loginClicked 方法的原因。

【问题讨论】:

  • 您是否尝试删除stack.isUserInteractionEnabled = false 行?或将其更改为true
  • 是的,试过了,结果一样

标签: ios swift uibutton uistackview


【解决方案1】:

您可以使用协议/委托

//1. Create a protocol

protocol HomeViewDelegate{
    func loginButtonClicked(sender: UIButton)
}

class HomeView: UIView {

    //2. Create a delegate
    var delegate: HomeViewDelegate?

    let stackView: UIStackView = {
        let stack = UIStackView()
        stack.translatesAutoresizingMaskIntoConstraints = false
        stack.distribution = .fillProportionally
        stack.alignment = .fill
        stack.isUserInteractionEnabled = false
        return stack
    }()

    let haveAccount: UILabel = {
        let label = UILabel()

        return label
    }()

    let signin: UIButton = {
        let button = UIButton()
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitle("Sign in", for: .normal)
        button.titleLabel?.font = UIFont(name: "Avenir", size: 14)
        button.setTitleColor(UIColor.white, for: .normal)
        button.addTarget(self, action: #selector(loginClicked(sender:)), for: .touchUpInside)
        button.backgroundColor = .red
        return button
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        translatesAutoresizingMaskIntoConstraints = false

        addSubview(stackView)
        stackView.addArrangedSubview(haveAccount)
        stackView.addArrangedSubview(signin)
        stackView.setCustomSpacing(4.0, after: haveAccount)

    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

   //3. Call your protocol method via delegate
   @objc func loginClicked(sender: UIButton) {
        if let delegate = delegate{
            delegate.loginButtonClicked(sender: sender)
        }
    }

}

在你的 Caller ViewController 中创建一个扩展

extension ViewController: HomeViewDelegate{
    func loginButtonClicked(sender: UIButton) {
        print("login Button Clicked")
    }
}

【讨论】:

    【解决方案2】:

    首先将stackView 的userInteractionEnabled 属性设置为false,然后将其设置为true。然后,如果它不起作用,请考虑以下方法:

    有两种可能的方法来解决这个问题,第一种是从 ViewController 添加目标,另一种是使用委托。

    我认为第一种方法对你来说更容易实现。

    您需要从ViewController 类中添加您的目标。

    首先更新您的视图类并摆脱添加目标:

    class HomeView: UIView {
    
    override init(frame: CGRect) {
      super.init(frame: frame)
      translatesAutoresizingMaskIntoConstraints = false
    
      addSubview(stackView)
      stackView.addArrangedSubview(haveAccount)
      stackView.addArrangedSubview(signin)
      stackView.setCustomSpacing(4.0, after: haveAccount)
    }
    
    let stackView: UIStackView = {
      let stack = UIStackView()
      stack.translatesAutoresizingMaskIntoConstraints = false
      stack.distribution = .fillProportionally
      stack.alignment = .fill
      stack.isUserInteractionEnabled = true
      return stack
    }()
    
    let haveAccount: UILabel = {
      let label = UILabel()
      ...
      return label
    }()
    
    let signin: UIButton = {
      let button = UIButton()
      button.translatesAutoresizingMaskIntoConstraints = false
      button.setTitle("Sign in", for: .normal)
      button.titleLabel?.font = UIFont(name: "Avenir", size: 14)
      button.setTitleColor(UIColor.white, for: .normal)
      return button
    }()
    
    }
    

    现在在您的ViewController

    override func viewDidLoad() {
        super.viewDidLoad()
    
        homeView = HomeView()
        homeView.translatesAutoresizingMaskIntoConstraints = false
        homeView.signIn.addTarget(self, action: #selector(loginClicked), for: .touchUpInside)
        view.addSubview(homeView)
        homeView.fullscreenView(parentView: view)
    }
    
    @objc func loginClicked(_ sender: UIButton) {        
        print("sign in button pressed")
    }
    

    【讨论】:

    • 感谢您的回复。我删除了按钮定义中的目标并将其移至上面的视图控制器,但我仍然得到相同的结果。
    • @user2569905 您是否将isUserInteractionEnabledstackView 设置为true?
    【解决方案3】:

    您需要添加正确的约束,我遇到了这个问题,我遇到了这个问题,解决方案是这样的。

    解决方案:

    import Foundation
    import UIKit
    
    protocol HomeViewDelegate:class{
        func loginButtonClicked(sender: UIButton)
    }
    
    class HomeView: UIView {
    
        //2. Create a delegate
        weak var delegate: HomeViewDelegate?
    
        var stackView: UIStackView = {
            let stack = UIStackView()
            stack.translatesAutoresizingMaskIntoConstraints = false
            stack.distribution = .fillProportionally
            stack.alignment = .fill
            stack.axis = .vertical
            stack.isUserInteractionEnabled = true
            return stack
        }()
    
        let haveAccount: UILabel = {
            let label = UILabel()
            label.backgroundColor = .gray
            label.text = "Label"
            label.textAlignment = .center
            return label
        }()
    
        let signin: UIButton = {
            let button = UIButton()
            button.translatesAutoresizingMaskIntoConstraints = false
            button.setTitle("Sign in", for: .normal)
            button.titleLabel?.font = UIFont(name: "Avenir", size: 14)
            button.setTitleColor(UIColor.white, for: .normal)
            button.addTarget(self, action: #selector(loginClicked(sender:)), for: .touchUpInside)
            button.isUserInteractionEnabled = true
            button.backgroundColor = .red
            return button
        }()
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            
            stackView.addArrangedSubview(haveAccount)
            stackView.addArrangedSubview(signin)
            stackView.setCustomSpacing(4.0, after: haveAccount)
    
            addSubview(stackView)
           
            NSLayoutConstraint.activate([
                    
                self.stackView.topAnchor.constraint(equalTo: self.topAnchor),
                self.stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
                self.stackView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
                self.stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
    
            ])
    
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
       //3. Call your protocol method via delegate
       @objc func loginClicked(sender: UIButton) {
            if let delegate = delegate{
                delegate.loginButtonClicked(sender: sender)
            }
        }
    
    }
    

    视图控制器

    override func viewDidLoad() {
        super.viewDidLoad()
    
        let homeView = HomeView()
    
        homeView.translatesAutoresizingMaskIntoConstraints = false
        homeView.delegate = self
    
        self.view.addSubview(homeView)
            
         NSLayoutConstraint.activate([
                homeView.centerXAnchor.constraint(equalTo: centerXAnchor),
                homeView.centerYAnchor.constraint(equalTo: centerYAnchor),
                homeView.heightAnchor.constraint(equalToConstant: 300),
                homeView.widthAnchor.constraint(equalToConstant: 300)
    
         ])
    }
    
    @objc func loginClicked(_ sender: UIButton) {        
        print("sign in button pressed")
    }
    

    【讨论】:

      【解决方案4】:

      将此行添加到您的按钮代码中

      button.isUserInteractionEnabled = true
      

      re-active isUserInteractionEnabled 再次

      let signin: UIButton = {
              let button = UIButton()
              button.backgroundColor = .blue
              button.setTitle("Sign in", for: .normal)
              button.titleLabel?.font = UIFont(name: "Avenir", size: 14)
              button.setTitleColor(UIColor.white, for: .normal)
              button.addTarget(self, action: #selector(ViewController.loginClicked(_:)), for: .touchUpInside)
              button.isUserInteractionEnabled = true
      
              return button
          }()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多