首页 > 解决方案 > Swift:UIControls 的 UIStackView 与不会触发的选择器方法

问题描述

介绍

我正在创建一个使用自定义视图的应用程序,其中我有一个 UIStackView 来整理 5 个 UIControls。当用户点击其中一个 UIControls 时,下划线将变为动画,在点击的 UIControl 下方滑动。

但是,由于某种原因,这些 UIControls 的方法/选择器不再被调用。我相信这与我将我的 Mac 更新为本周(wk.44)发布的 macOS(和 Xcode)更新有关。(从 swift 4.2 更新到 swift 4.2.1)。在更新之前,此动画和选择器运行良好。但我不确定。我现在完全坚持我做错了什么。

语境

问题

代码

import UIKit
import PlaygroundSupport

class SetupViewControl: UIControl {

    let titleLabel : UILabel = {
        let lbl = UILabel()
        lbl.font = UIFont(name: "Futura", size: 14)
        lbl.textColor = .white
        lbl.backgroundColor = .clear
        lbl.textAlignment = .center
        lbl.translatesAutoresizingMaskIntoConstraints = false
        return lbl
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupLabel()
        layer.cornerRadius = 5
    }

    fileprivate func setupLabel() {
        addSubview(titleLabel)
        titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 5).isActive = true
        titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -5).isActive = true
        titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
    }

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

    override var isHighlighted: Bool {
        didSet {
            UIView.animate(withDuration: 0.12) {
                self.backgroundColor = self.isHighlighted ? UIColor.lightGray : UIColor.clear
            }
        }
    }
}

class SetupView: UIView {

    let dataModel : [String] = ["2 weeks", "1 month", "2 months", "6 months", "1 year"]
    var selectionLineCenterX : NSLayoutConstraint!

    let selectionLine = UIView()
    let labelZero = SetupViewControl()
    let labelOne = SetupViewControl()
    let labelTwo = SetupViewControl()
    let labelThree = SetupViewControl()
    let labelFour = SetupViewControl()
    let labelFive = SetupViewControl()

    lazy var controlArray = [self.labelZero, self.labelOne, self.labelTwo, self.labelThree, self.labelFour, self.labelFive]

    init(frame: CGRect, color: UIColor) {
        super.init(frame: frame)
        self.backgroundColor = color
        setupView()
    }

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

    fileprivate func setupView() {
        layer.cornerRadius = 0
        layer.borderColor = UIColor.black.cgColor
        layer.borderWidth = 1
        setupLabelText()
        setupControlsInStackView()
    }

    fileprivate func setupLabelText() {
        for num in 0...(dataModel.count - 1) {
            controlArray[num].titleLabel.text = dataModel[num]
        }
    }

    // let stackView = UIStackView(frame: .zero) I have tried to declare the stackView here but it doesn't fix my issue.
    func setupControlsInStackView() {
        var stackViewArray = [SetupViewControl]()
        for num in 0...(dataModel.count - 1) {
            controlArray[num].isUserInteractionEnabled = true
            controlArray[num].addTarget(self, action: #selector(goalViewControlTapped(_:)), for: .touchUpInside)
            stackViewArray.append(controlArray[num])
        }
        let stackView = UIStackView(arrangedSubviews: stackViewArray)
        stackView.alignment = .fill
        stackView.distribution = .fillEqually
        stackView.axis = .horizontal
        stackView.translatesAutoresizingMaskIntoConstraints = false
        addSubview(stackView)
        stackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8).isActive = true
        stackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8).isActive = true
        stackView.topAnchor.constraint(equalTo: topAnchor, constant: 15).isActive = true

        addSubview(selectionLine)
        selectionLine.backgroundColor = .white
        selectionLine.translatesAutoresizingMaskIntoConstraints = false
        selectionLine.heightAnchor.constraint(equalToConstant: 1).isActive = true
        selectionLine.topAnchor.constraint(equalTo: stackView.bottomAnchor).isActive = true
        selectionLine.widthAnchor.constraint(equalToConstant: 50).isActive = true
        selectionLineCenterX = selectionLine.centerXAnchor.constraint(equalTo: leadingAnchor, constant: -100)
        selectionLineCenterX.isActive = true
    }

    @objc fileprivate func goalViewControlTapped(_ sender: SetupViewControl) {
        print("This is not getting printed!!!")
        selectionLineCenterX.isActive = false
        selectionLineCenterX = selectionLine.centerXAnchor.constraint(equalTo: sender.centerXAnchor)
        selectionLineCenterX.isActive = true
        UIView.animate(withDuration: 0.25, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.5, options: .curveEaseIn, animations: {
            self.layoutIfNeeded()
        }, completion: nil)
    }
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        let testView = SetupView(frame: .zero, color: UIColor.blue)
        view.addSubview(testView)
        testView.translatesAutoresizingMaskIntoConstraints = false
        testView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        testView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        testView.heightAnchor.constraint(equalToConstant: 100).isActive = true
        testView.widthAnchor.constraint(equalToConstant: 365).isActive = true
    }
}
// For live view in playground
let vc = ViewController()
vc.preferredContentSize = CGSize(width: 375, height: 812)
PlaygroundPage.current.liveView = vc

感谢您阅读我的问题。

标签: iosswiftuiviewtargetuistackview

解决方案


当您打开视图调试器时,您的显示是否UIStackView具有模棱两可的布局?如果是这样,那可能会导致内部视图无法接收到触摸事件。

您可以提供UIStackView

xy仅约束

或者

x, y,width height.

在上述情况下,height缺少约束。


推荐阅读