斯威夫特:UIControls的UIStackView与不触发的选择器方法 [英] Swift: UIStackView of UIControls with selector method that doesn't fire

查看:93
本文介绍了斯威夫特:UIControls的UIStackView与不触发的选择器方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个使用自定义视图的应用程序,其中有一个UIStackView可以整理出5个UIControl.当用户点击其中一个UIControls时,下划线将显示为动画,并在所单击的UIControl下方滑动.

I'm creating an app which uses a custom view in which I have a UIStackView to sort out 5 UIControls. When a user taps one of the UIControls an underscore line gets animated, sliding under the tapped UIControl.

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

However, for some reason the method/selector for these UIControls no longer gets called. I believe this has to do with that I updated my Mac to the macOS (and Xcode) update released this week (wk.44). (updated from swift 4.2 to swift 4.2.1). Before the updated this animation and selector worked perfectly. But I'm not sure. And I'm now completely stuck on what I'm doing wrong.

上下文

  • 我创建了一个游乐场,并尽可能缩小所有内容,问题仍然存在.

  • I created a playground and scaled down everything as much as I could and the issue persists.

我试图在我的SetupView类的全局范围内定义UIStackView,但它没有任何改变.所以我认为这不是stackView或其子视图被释放的问题吗?

I have tried to define the UIStackView in the global scope of my SetupView class but it doesn't change anything. So I believe it is not an issue of the stackView or its subviews being deallocated?

下面,我提供了我的UIControl子类和我使用的SetupView(UIView子类).我已经创建了一个游乐场,所以您可以在Xcode游乐场中复制粘贴,以测试是否需要.

Below I've provided my UIControl subclass and my SetupView (UIView subclass) that I use. I've created a playground so you may copy paste in Xcode playground to test if you want.

问题

  • 为什么不调用方法goalViewControlTapped(_ sender: SetupViewControl)?

代码

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

感谢您阅读我的问题.

推荐答案

打开视图调试器时,您的UIStackView显示是否布局不明确?如果是这样,则可能导致内部视图无法接收触摸事件.

Does your UIStackView show as having an ambiguous layout when you open the view debugger? If so, that may be causing the internal views to not receive the touch events.

您可以为UIStackView提供以下任何一项:

You can provide UIStackView with either:

xy约束

xywidth height.

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

In the above case the height constraint is missing.

这篇关于斯威夫特:UIControls的UIStackView与不触发的选择器方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆