Swift 中的 UIButton 没有注册触摸

Posted

技术标签:

【中文标题】Swift 中的 UIButton 没有注册触摸【英文标题】:UIButton in Swift is not registering touches 【发布时间】:2014-06-04 12:45:48 【问题描述】:

我正在尝试使用 Swift 创建一个 UIButton。它编译得很好,我可以在模拟器中看到我的按钮,但是当我点击它时,什么也没有发生。这是我正在使用的代码:

let settings = UIButton()
settings.addTarget(self, action: "touchedSet:", forControlEvents: UIControlEvents.TouchUpInside)
settings.setTitle("Settings", forState: .Normal)
settings.frame = CGRectMake(0, 530, 150, 50)
scrollView.addSubview(settings)

在同一个类中,这里是函数'touchedSet':

func touchedSet(sender: UIButton!) 
    println("You tapped the button")

我正在使用模拟器,因为我没有 ios 8.0 设备,这可能是问题吗?

谢谢!

【问题讨论】:

只是一个随机评论,但我真的不喜欢 settings 的名称作为按钮。即使只是做settingsButton 会更好:) 非常正确:P 感谢您指出这一点! 我试过你的代码。对我来说,动作方法被调用 嗯,它在模拟器中对你有用吗?我无权访问 8.0 设备。 是的,在模拟器中。有时它不会识别选择器,似乎存在错误。即使我没有遇到您的代码,我也只是更改了操作名称(选择器)。它有效 【参考方案1】:

我看到这是一个老问题,但我昨天遇到了非常相似的问题。我的按钮在触摸时突出显示,但未触发操作。

我有两个视图控制器。一个视图覆盖其他视图,按钮位于顶部视图。

例如。

Rootviewcontroller 有后视图

Topviewcontroller 有顶视图

如果我不将topviewcontroler 添加为rootviewcontroller 的childviewcontroller,顶视图上的按钮不会调用该操作。将 topviewcontroller 添加为 childviewcontroller 后,它开始工作。

简而言之:只需尝试使用以下方法将按钮superview的视图控制器作为childviewcontroller添加到父视图viewcontroller

func addChildViewController(_ childController: UIViewController)

【讨论】:

我爱你,梅特。这浪费了我大约 6 个小时的时间试图弄清楚,我终于在这里找到了答案。 这个!我的 UITapgestures 和按钮代表不起作用。添加为 childVC 就可以了。谢谢你,先生! 又一颗宝石!谢谢默特!【参考方案2】:

选择器是必须创建的结构。

这样做...

为 Swift 4 更新

settingsButton.addTarget(self, action: #selector(showSettings), for: .touchUpInside)

应该可以的。

【讨论】:

嗯...尝试将按钮更改为 var 我试过了;那没有用。上面有人说我的代码对他们有用,问题是我使用的是模拟器而不是真实设备吗? 我也在模拟器,现在试试 @Phillip 尝试重新启动 Xcode 或模拟器。对我来说效果很好, 嗯,有什么特别的观点我应该附上的吗?现在我将它附加到 viewDidLoad 中的 self.view【参考方案3】:

对于遇到此问题的其他手动视图布局,您可能已经像这样定义了您的子视图:

let settingsButton: UIButton = 
    let button = UIButton(type: .system)
    // do some more setup
    button.addTarget(self, selector: #selector(openSettings), for: .touchUpInside)
    return button
()

错误在于您添加了一个目标并在它实际可用之前传递了self

这可以通过两种方式解决

    使变量lazy 仍然在初始化块中添加目标:

    lazy var button: UIButton = 
        let button = UIButton(type: .system)
        // since this variable is lazy, we are guaranteed that self is available
        button.addTarget(self, selector: #selector(openSettings), for: .touchUpInside)
        return button
     ()
    

    在父视图初始化后添加目标:

    init()  
        self.settingsButton = .init(type: .system)
        super.init(frame: .zero)
        self.settingsButton.addTarget(self, selector: #selector(openSettings), for: .touchUpInside)
    
    

【讨论】:

你的答案是金。我犯了同样的错误并调试了几个小时。这是常识,但很难解决这个问题是self。谢谢:) 我讨厌我来这里评论后才看到你的评论! 就是这样。谢谢!!【参考方案4】:

在模拟器中,有时它无法识别选择器。似乎有一个错误。我刚刚更改了动作名称(选择器),它起作用了。

let buttonPuzzle:UIButton = UIButton(frame: CGRectMake(100, 400, 100, 50))
buttonPuzzle.backgroundColor = UIColor.greenColor()
buttonPuzzle.setTitle("Puzzle", forState: UIControlState.Normal)
buttonPuzzle.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
buttonPuzzle.tag = 22;
self.view.addSubview(buttonPuzzle)

选择器功能在这里:

func buttonAction(sender:UIButton!)

    var btnsendtag:UIButton = sender
    if btnsendtag.tag == 22 
        //println("Button tapped tag 22")
       

【讨论】:

【参考方案5】:

当我的按钮的父视图有isUserInteractionEnabled == false 时,我遇到了这个问题。所有子视图都将具有与其父视图相同的userInteraction。所以我刚刚添加了这一行parentView.isUserInteractionEnabled = true,问题就消失了。希望这对某人有所帮助。

【讨论】:

【参考方案6】:

对于那些也被教程困住的人:

我在关注 Apple 的“开始开发 iOS 应用程序 (Swift)”时遇到了同样的问题。原来我在教程中忽略了这些代码行:

override var intrinsicContentSize : CGSize 
    return CGSize(width: 240, height: 44)

将它们添加到我的 RatingControl 解决了问题。

【讨论】:

这也是发生在我身上的事。如果您正在学习本教程,this 问题还提供了有关为什么 Swift 3 中的覆盖不同的答案。 谢谢。我和你有同样的问题。 @ouven +hero point - 谢谢!你知道为什么不设置这个属性会导致这个问题吗?【参考方案7】:

当我有一个带有按钮和 tapHandlers 匹配的 subViewController 时,我遇到了类似的问题,我想将它放在一个单独的 superViewController 中的堆栈中。..

这会导致所有的tapHandlers都不会触发,解决方法是不只使用addArrangedSubview(subViewController.view),我还在superview中使用addChildViewController(subViewController)来让childViewController继续作为viewController运行并且不仅仅是一个视图。

【讨论】:

【参考方案8】:

所以你应该使用以下行

settings.userInteractionEnabled = true

【讨论】:

UIButton.userInteractionEnabled 的默认值是true,所以我怀疑这会解决它。 就我而言,该属性错误地是错误的。谢谢提醒 @NaveedAhmad :)【参考方案9】:

老问题,但我想我会给其他寻找这个问题的人一些帮助。首先,我不完全确定这是正确的,如果我错了,请纠正我。

但是如果你错误地设置了选择器,当你按下按钮时应用程序会崩溃,因为它订阅了一个不存在的选择器。这意味着您的选择器正在工作。我的猜测是,假设UIButton.enabled = trueUIButton.userInteractionEnabled = true,其他东西正在阻止触摸事件。通常你可以通过长按按钮来检查它,看看它是否命中。如果是这样,那么您在某处添加了UIGestureRecognizer,它首先占用了点击量。也可能是延迟触摸输入的UIScrollView(检查器中有一个复选框)。

希望这对某人有所帮助,并希望它是准确的。

【讨论】:

感谢您的想法。但我的问题是该方法被调用 - UIApplication.shared.beginIgnoringInteractionEvents()【参考方案10】:

在容器视图(UIView)上实现 UIButton 和 SearchBar 时,我遇到了同样的问题。 就我而言,原因是约束问题。对 searchBar 的约束存在问题,因此从未调用函数集。

您可以从“Debug View Hierarchy”按钮中查看是否有任何内容。 (约束问题显示为紫色警告)

(环境:iOS12,xcode10.1)

【讨论】:

【参考方案11】:

有趣的是,我刚刚在最新版本的 iOS/Xcode (v12.4 / v10.3) 上遇到了同样的问题。原来对我来说问题是一个LayoutConstraint!不是开玩笑。我有一个右侧带有 uiSwitch 的前导标签,发现我需要更改两者之间的约束,使其不是 8 点的固定常数值 (Label-8-Switch-0-|)。

只要我将其更改为 ">=",Switch 就能够在开/关之间更改状态。可笑的是,它几乎就像无法改变一样,因为它需要“空间”(显然不同)来进行改变。

不确定,但将其作为“嗯?”之一归档。记忆中的物品。

另一项(坦率地说,这真的不重要)是 valueChanged 和 tappedUpInside 都没有触发(在实际手机和模拟器上都是如此)。此外,他们通过故事板连接起来。但是,据我所知,这应该无关紧要。

【讨论】:

刚遇到这个问题,你的帖子对我有帮助!奇怪的是,只是缺少约束会导致按钮不响应。在我的情况下,它没有居中但仍然可见但不响应触摸。 IB 显示警告,但我绝不会想到这种警告会导致这种行为。【参考方案12】:

我遇到了同样的问题。问题是视图有顶部约束,但没有左/右和高度约束。因此,视图缩小到 1x1,并且没有将触摸事件传递给孩子。

通过添加更多约束,孩子们现在可以获得触摸事件并开始工作......

let guide = view.safeAreaLayoutGuide
viewHeader.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true
viewHeader.rightAnchor.constraint(equalTo: guide.rightAnchor).isActive = true
viewHeader.leftAnchor.constraint(equalTo: guide.leftAnchor).isActive = true
let heightConstraint = NSLayoutConstraint(item: viewHeader,
                                          attribute: NSLayoutConstraint.Attribute.height,
                                          relatedBy: NSLayoutConstraint.Relation.equal,
                                          toItem: nil,
                                          attribute: NSLayoutConstraint.Attribute.notAnAttribute,
                                          multiplier: 1,
                                          constant: 44)
viewHeader.addConstraints([heightConstraint])

【讨论】:

【参考方案13】:

老问题,但我也发现自己被一个无响应的按钮困住了。我只是从

更改了我的初始化
let button = UIButton(frame: .zero)

let button = UIButton(type: .system)

【讨论】:

【参考方案14】:

我只能看到一个问题:您必须将action 设置为Selector,如下所示:

settings.addTarget(self, action: Selector("touchedSet:"), forControlEvents: UIControlEvents.TouchUpInside)

如果需要向函数传递参数,请不要忘记插入:

【讨论】:

这个答案是完全错误的,因为一个字符串和 Swift 中对应的选择器是一样的。【参考方案15】:

你说的是同一个班。如果您正在使用视图,请确保按钮代码本身位于 viewDidLoad() 中,并且操作位于其外部但在类内部。

【讨论】:

【参考方案16】:

Apple 的该教程的问题是他们将 UIView (RatingControl) 放入 StackView 的方式,这是不正确的。 UIView (RatingControl) 应该在 StackView 之外。所以,解决方案是: 1.将UIView(RatingControl)拖到StackView之外 2.设置RatingControl新位置的约束 - 容器的前导边距为零 - 容器的尾随边距为零 - StackView 的上边距为零

有了这个新的约束,现在 RatingControl 将与 Container 一样,无论设备屏幕大小是什么,并且始终位于显示照片选择器的 StackView 后面。

希望对大家有所帮助。

【讨论】:

【参考方案17】:

如果您使用情节提要,请确保将按钮与代码中的 IBOutlet 实例变量链接起来。

【讨论】:

我没有使用 Interface Builder 我复制了您发布到我的项目中的确切代码,它工作得很好...在您设置按钮后,您是否添加了其他任何内容作为滚动视图的子视图?或者你对你的滚动视图有什么特殊设置? 问题是您在声明属性时使用了let settings = UIButton() 而不是var settings = UIButton()let 变量类似于 Objective-C 中的 const 对象。我把它改成var 然后它工作了。 嗯,即使它是一个 var,它仍然无法工作:(这可能是一个愚蠢的问题,但为什么让它成为一个常数会导致它停止工作?我不会在任何地方重新分配它 你的scrollView不滚动的原因是你没有为它设置内容大小。我使用了scrollView.contentSize = CGSizeMake(self.view.bounds.size.width*1.5, self.view.bounds.size.height*1.5),它可以毫无问题地滚动......而且,按钮仍然有效......【参考方案18】:

我为 Swift 2 找到了类似的示例并适用于 Swift 3。经过测试,它运行良好。希望对你有帮助。

// http://lab.dejaworks.com/ios-swift-3-playground-uibutton-action
// Trevor D. Beydag

import UIKit
import PlaygroundSupport
class Responder : NSObject 
    func action() 
        print("Button pressed!")
    


let containerView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 300.0,    height: 600.0))
PlaygroundPage.current.liveView = containerView
let responder = Responder()

let button = UIButton(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
button.backgroundColor = UIColor.green
button.setTitle("TEST", for: .normal)
button.addTarget(responder, action: #selector(Responder.action), for: .touchUpInside)
containerView.addSubview(button)

【讨论】:

【参考方案19】:

我已将高度和宽度约束更改为 0,出于某种原因我需要这样做,以便它在一个用例的多用途视图上正确显示,按钮可见但触摸停止工作。

【讨论】:

【参考方案20】:

就我而言,我在视图层次结构中的UIButton 上方有一个透明的UIView,这就是为什么当我“点击UIButton”时,我实际上是点击了透明的UIView顶一下。

使用parentUIView.sendSubviewToBack(transparentUIView) 发送透明的UIView 对我有用,因为在这样做之后UIButton 位于视图层次结构的顶部。点击Xcode中的“Debug View Hierarchy”按钮,检查UIButton是否在顶部。

【讨论】:

就我而言,navigationContentView 位于按钮上方。

以上是关于Swift 中的 UIButton 没有注册触摸的主要内容,如果未能解决你的问题,请参考以下文章

Swift:触摸不立即注册位于UIViewController底部的UIButtons

通过触摸按钮 Swift 3 更改 UIButton 文本标签颜色

Swift:在自定义视图中未调用 UIButton 触摸事件

如何防止 UILabel 在 Swift 中阻止对父 UIButton 的触摸?

按钮未在自定义 UIButton 中注册触摸

在iPhone中禁用UIButton中的触摸动画