Swift中的UIButton无法响应触摸

32

我正在使用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设备所以在使用模拟器,这可能是问题的原因吗?

谢谢!


11
只是一条随机评论,但我真的不喜欢将按钮命名为“设置(settings)”。即使只是使用“设置按钮(settingsButton)”也会更好 :) - Fogmeister
非常正确 :P 感谢指出! - Phillip
我尝试了你的代码。对我来说,动作方法被调用了。 - Anil Varghese
嗯,模拟器里能用吗?我没有8.0设备的访问权限。 - Phillip
1
是的,在模拟器中。有时它无法识别选择器,似乎存在一个错误。即使我没有为您的代码遇到过这种情况,但我只是更改了操作名称(选择器)。它可以工作。 - Anil Varghese
22个回答

21

我发现这是一个旧问题,但昨天我刚遇到非常相似的问题。我的按钮在触摸时会高亮,但不执行操作。

我有两个视图控制器。 一个视图覆盖另一个视图,并且按钮位于顶部视图上。

例如:

  • Rootviewcontroller 拥有后视图

  • Topviewcontroller 拥有顶部视图

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

简而言之:只需尝试将按钮 superview 的视图控制器作为 childviewcontroller 添加到父视图的视图控制器中,具体方法如下:

func addChildViewController(_ childController: UIViewController)

3
我爱你,Mert。 这占用了我约6个小时的时间来尝试弄清楚,最终我在这里找到了答案。 - Wedge Martin
2
这个!我的UITapgestures和按钮代理没有起作用。将其添加为childVC就解决了问题。谢谢,先生! - Yasper
Another SO gem! Thanks Mert! - William T. Mallard

11

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

可以通过以下方式进行创建...

已更新至Swift 4

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

那就可以了。


嗯...尝试将按钮更改为var。 - Fogmeister
我也在模拟器中,现在只是在尝试。 - Fogmeister
1
@Phillip 尝试重新启动Xcode或模拟器。对我来说它运行良好。 - Fogmeister
@Phillip 在你提问的代码中,你将它添加到了 scrollView 而不是 self.view。此外,在 Swift 中,如果很明显你要引用什么,就不需要使用 self.,只需使用 view.addSubview(settingsButton) 即可。 - Fogmeister
@ShahbazAkram 这是2014年的内容。现在选择器已经以不同的方式创建了。我会更新的。现在请检查一下。 - Fogmeister
显示剩余8条评论

10

如果还有其他人在手动视图布局时遇到此问题,可能是您将子视图定义为以下内容:

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

错误在于尝试在实际可用之前添加目标并传递self

这可以通过两种方式修复:

  1. 将变量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
     }()
    
  2. 在父视图初始化后添加目标:

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

5
你的回答真是太棒了。我犯了同样的错误,调试了好几个小时。这是常识,但很难意识到问题出在 self 上。谢谢 :) - Jogendra Kumar
2
我很讨厌在我来到这里发表评论之后才看到你的评论! - Daniel Carlos
2
这就是它。谢谢!! - Ondřej Korol

5

如果您也卡在教程中:

我遇到了同样的问题,当我按照苹果公司的“开始开发iOS应用程序(Swift)”进行操作时。原来是我在教程中忽略了这些代码行:

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

将它们添加到我的评分控件中,就解决了这个问题。

这也是我遇到的情况。如果你正在跟随教程,这个问题也提供了有关为什么在Swift 3中覆盖方法不同的答案。 - otolock
谢谢。我和你有同样的问题。 - casamia
1
@ouven +英雄点数 - 谢谢!你知道为什么不设置这个属性会导致这个问题吗? - mihalios

5

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


5

在模拟器中,有时候无法识别选择器。看起来是一个bug。我只是改变了操作名称(选择器),然后就可以了。

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")
    }   
}

3

当我有一个带有按钮和tapHandlers的子视图控制器,并且我想将其放置在一个单独的父视图控制器中的堆栈中时,出现了类似的问题。

这样会导致没有任何tapHandlers触发,解决方法是除了使用addArrangedSubview(subViewController.view)之外,还要在父视图控制器中使用addChildViewController(subViewController)来让子视图控制器继续作为视图控制器而不仅仅是一个视图。


1
所以你应该使用以下代码行。
settings.userInteractionEnabled = true

7
UIButton.userInteractionEnabled 的默认值为 true,因此我怀疑这并不能解决问题。 - NRitH
在我的情况下,那个属性错误地被设置为 false。感谢提醒。 - Naveed Ahmad
@NaveedAhmad :) - Samrez Ikram

1

虽然这个问题已经很旧了,但我想为其他寻找此问题答案的人提供一些帮助。首先,我不确定我的回答是否正确,请在我有误时纠正我。

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

希望这能帮助到某些人,并希望它是准确的。


谢谢你的建议。但我的问题是方法被调用为 - UIApplication.shared.beginIgnoringInteractionEvents() - flowGlen

1
当我在容器视图(UIView)上实现UIButton和SearchBar时遇到了同样的问题。在我的情况下,原因是约束问题。搜索栏的约束存在问题,因此该函数从未被调用。您可以通过“Debug View Hierarchy”按钮查看是否存在问题(约束问题显示为紫色警告)。 (env:iOS12,xcode10.1)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接