简体   繁体   English

Swift 中的 UIButton 未注册触摸

[英]UIButton in Swift is not registering touches

I'm trying to create a UIButton using Swift. It compiles fine and I can see my button in the simulator, but when I click it, nothing happens.我正在尝试使用 Swift 创建一个 UIButton。它编译正常,我可以在模拟器中看到我的按钮,但是当我点击它时,没有任何反应。 This is the code I am using:这是我正在使用的代码:

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)

In the same class, here is the function 'touchedSet':在同一个 class 中,这里是 function 'touchedSet':

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

I'm using the simulator as I don't have an iOS 8.0 device, could that be the problem?我正在使用模拟器,因为我没有 iOS 8.0 设备,这可能是问题所在吗?

Thanks!谢谢!

I see it is an old question but I just faced very similar problem yesterday.我看到这是一个老问题,但我昨天刚刚遇到了非常相似的问题。 My buttons were highlighted on touch but not firing the action.我的按钮在触摸时突出显示但没有触发动作。

I have two view controllers.我有两个视图控制器。 One view covers the others view and button is on the top view.一个视图覆盖其他视图,按钮位于顶视图。

eg.例如。

  • Rootviewcontroller has back view Rootviewcontroller 有后视图

  • Topviewcontroller has top view Topviewcontroller 有顶视图

The button on top view does not call the action if I don't add the topviewcontroler as childviewcontroller of the rootviewcontroller.如果我不将 topviewcontroler 添加为 rootviewcontroller 的 childviewcontroller,则顶视图上的按钮不会调用该操作。 After adding the topviewcontroller as childviewcontroller it started to working.添加 topviewcontroller 作为 childviewcontroller 后,它开始工作。

So in short: just try to add the view controller of buttons superview as childviewcontroller to the parent views viewcontroller with the following method简而言之:只需尝试使用以下方法将按钮超级视图的视图控制器作为子视图控制器添加到父视图视图控制器

func addChildViewController(_ childController: UIViewController)

Selectors are a struct that have to be created.选择器是一个必须创建的结构。

Do it this way...这样做...

Updated for Swift 4为 Swift 4 更新

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

That should do it.那应该这样做。

In the simulator, sometimes it doesn't recognise the selector.在模拟器中,有时它无法识别选择器。 There is a bug it seems.似乎有一个错误。 I just changed the action name (selector), and it worked.我刚刚更改了操作名称(选择器),它起作用了。

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)

Selector Function is Here:选择器功能在这里:

func buttonAction(sender:UIButton!)
{
    var btnsendtag:UIButton = sender
    if btnsendtag.tag == 22 {
        //println("Button tapped tag 22")
    }   
}

For those who are also stuck in the tutorial:对于那些也被困在教程中的人:

I ran in to the same problem, when I was following Apple's "Start Developing iOS Apps (Swift)".我在关注 Apple 的“开始开发 iOS 应用程序(Swift)”时遇到了同样的问题。 It turned out that I had overlooked these code lines in the tutorial:结果是我在教程中忽略了这些代码行:

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

Adding them to my RatingControl fixed the problem.将它们添加到我的 RatingControl 解决了这个问题。

For anyone else doing manual view layout running into this issue, you might have defined your subview like such:对于遇到此问题的其他手动视图布局的人,您可能已经像这样定义了子视图:

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

The error lies with the fact that you are adding a target and passing self before it is actually available.错误在于您正在添加目标并在它实际可用之前传递self

This can be fixed in two ways这可以通过两种方式修复

  1. Making the variable lazy and still adding the target in the initialization block:使变量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. Adding the target after your parent view has been initialized:在初始化父视图后添加目标:

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

I have had this problem when parent view of my button has isUserInteractionEnabled == false .当我的按钮的父视图具有isUserInteractionEnabled == false时,我遇到了这个问题。 All subviews will have the same userInteraction as their parent view.所有子视图都将具有与其父视图相同的userInteraction So I have just added this line parentView.isUserInteractionEnabled = true and the problem disappeared.所以我刚刚添加了这一行parentView.isUserInteractionEnabled = true并且问题消失了。 Hope this helps someone.希望这可以帮助某人。

I had a similar problem when i had a subViewController with buttons and tapHandlers to match, and I wanted to place this to a stack in a separate superViewController..当我有一个带有按钮和 tapHandlers 匹配的 subViewController 时,我遇到了类似的问题,我想将它放在一个单独的 superViewController 中的堆栈中。

This cause none of the tapHandlers to to trigger, and the solution was to instead of only using addArrangedSubview(subViewController.view), I also used addChildViewController(subViewController) in the superview to allow the childViewController to continue to operate as a viewController and not just a view.这导致没有触发任何 tapHandlers,解决方案是,而不是仅使用 addArrangedSubview(subViewController.view),我还在addChildViewController(subViewController)使用addChildViewController(subViewController)以允许 childViewController 继续作为 viewController 运行,而不仅仅是一个看法。

所以你应该使用以下行

settings.userInteractionEnabled = true

I had the same issue when implementing UIButton and SearchBar on container view(UIView).在容器视图(UIView)上实现 UIButton 和 SearchBar 时,我遇到了同样的问题。 In my case, the cause was the constraint issue.就我而言,原因是约束问题。 Constraint to searchBar had issue and because of this, function set had never been called.对 searchBar 的约束有问题,因此,从未调用过函数集。

You can see if there's any from "Debug View Hierarchy" button.您可以从“调试视图层次结构”按钮中查看是否有任何内容。 (constraint problem is shown as purple warning) (约束问题显示为紫色警告)

(env: iOS12, xcode10.1) (环境:iOS12,xcode10.1)

Interestingly enough, I just ran into the same issue on the very latest versions of iOS/Xcode (v12.4 / v10.3).有趣的是,我刚刚在最新版本的 iOS/Xcode (v12.4 / v10.3) 上遇到了同样的问题。 Turns out the issue for me was a LayoutConstraint!原来我的问题是 LayoutConstraint! No joke.不是开玩笑。 I had a leading label with the uiSwitch to the right, and found that I needed to change the constraints between the two such that it wasn't a fixed constant value of 8 points (Label-8-Switch-0-|).我有一个带有右侧 uiSwitch 的前导标签,发现我需要更改两者之间的约束,使其不是 8 点的固定常量值 (Label-8-Switch-0-|)。

As soon as I changed this to a ">=" the Switch was able to change states between on/off.一旦我将其更改为 ">=" 开关就能够在开/关之间改变状态。 Laughably, it's almost like it wasn't able to change because it needs "room" (that apparently varies) to make the change with.可笑的是,它几乎就像无法改变一样,因为它需要“空间”(显然会有所不同)来进行改变。

Not sure, but file it away as one of those "hummmm?"不确定,但将其归档为其中之一“嗯?” items in your memory.记忆中的物品。

One other item (that really shouldn't matter, frankly) is the valueChanged and tappedUpInside were both not firing (true on both an actual handset and on the simulators).另一项(坦率地说,这真的不重要)是 valueChanged 和 tappedUpInside 都没有触发(在实际手机和模拟器上都是如此)。 Also, they were hooked up through a storyboard.此外,他们通过故事板联系在一起。 But, this shouldn't matter as far as I know.但是,据我所知,这应该无关紧要。

I had the same issue.我遇到过同样的问题。 The problem was the view had top constraint, but not left/right and height constraints.问题是视图有顶部约束,但没有左/右和高度约束。 So, the view was shrinking to 1x1 and it was not passing the touch event to children.因此,视图缩小到 1x1,并且没有将触摸事件传递给儿童。

By adding more constraints, the children now getting the touch event and working ...通过添加更多约束,孩子们现在可以获取触摸事件并开始工作......

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])

Old question, but I also found myself stuck with an unresponding button.老问题,但我也发现自己被一个无响应的按钮卡住了。 I simply changed my initialisation from我只是改变了我的初始化

let button = UIButton(frame: .zero)

to

let button = UIButton(type: .system)

如果您使用故事板,请确保将按钮与代码中的 IBOutlet 实例变量链接起来。

I can see only one problem: You have to set the action with Selector as following:我只能看到一个问题:您必须使用Selector设置action ,如下所示:

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

Don't forget to insert : if you need to pass parameters to the function.不要忘记插入:如果您需要将参数传递给函数。

You said within the same class.你说在同一个班级。 Make sure that the button code itself is in the viewDidLoad() and the action be outside of it but inside the class if you are working with a view.如果您正在使用视图,请确保按钮代码本身在 viewDidLoad() 中,并且操作在它之外但在类内。

The problem with that tutorial from Apple is the way they put the UIView (RatingControl) inside the StackView, which is incorrect. Apple 的那个教程的问题在于他们将 UIView (RatingControl) 放在 StackView 中的方式,这是不正确的。 The UIView (RatingControl) should be outside of the StackView. UIView (RatingControl) 应该在 StackView 之外。 So, the solution is: 1. Drag the UIView (RatingControl) outside of the StackView 2. Set the constraints for the new position of the RatingControl - Leading margin to the Container equal zero - Trailing margin to the Container equal zero - Top margin to the StackView equal zero因此,解决方案是: 1. 将 UIView (RatingControl) 拖到 StackView 之外 2. 设置RatingControl 新位置的约束 - Container 的前导边距等于零 - Container 的尾距边距等于零 - Top margin to StackView 等于零

With this new constraints, now the RatingControl will have the same with as the Container, no matter what is the device screen size, and always will be just behind of the StackView where the photo selector will appear.有了这个新的约束,现在 RatingControl 将与容器相同,无论设备屏幕大小如何,并且始终位于照片选择器将出现的 StackView 的后面。

I hope this help you guys.我希望这对你们有帮助。

Old question, but thought I'd give some help to other looking for this issue.老问题,但我想我会给其他寻找这个问题的人一些帮助。 First off, I'm not entire sure this is correct so please correct me if I'm wrong.首先,我不完全确定这是正确的,所以如果我错了,请纠正我。

But if you set the selector wrongly the application would crash when you press the button since it's subscribed to a selector which doesn't exist.但是如果你错误地设置了选择器,当你按下按钮时,应用程序会崩溃,因为它订阅了一个不存在的选择器。 Which means that your selector is working.这意味着您的选择器正在工作。 My guess is that something else is blocking the touch event, assuming UIButton.enabled = true and UIButton.userInteractionEnabled = true .我的猜测是其他东西正在阻止触摸事件,假设UIButton.enabled = trueUIButton.userInteractionEnabled = true Usually you could check this by long pressing the button and see if it hits.通常你可以通过长按按钮来检查它,看看它是否命中。 If it does then you have a UIGestureRecognizer added somewhere which takes up the hits first.如果是这样,那么您在某处添加了一个UIGestureRecognizer ,它首先占用了点击量。 Could also be the UIScrollView which is delaying the touch input (there's a checkbox for this in the Inspector).也可能是延迟触摸输入的UIScrollView (检查器中有一个复选框)。

Hope this helps someone, and hope it's accurate.希望这对某人有所帮助,并希望它是准确的。

I've found similar example for Swift 2 and adapted for Swift 3. Tested it is working very well.我为 Swift 2 找到了类似的示例,并适用于 Swift 3。经过测试,它运行良好。 I hope it helps.我希望它有帮助。

// 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)

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

In my case, I had a transparent UIView above the UIButton in the view hierarchy, which is why when I was "clicking on the UIButton ", I was actually clicking on the transparent UIView on top of it.就我而言,我在视图层次结构中的UIButton上方有一个透明的UIView ,这就是为什么当我“单击UIButton ”时,我实际上是在单击它上面的透明UIView

Sending the transparent UIView back using parentUIView.sendSubviewToBack(transparentUIView) worked for me, because after doing this the UIButton came on top of the view hierarchy.使用parentUIView.sendSubviewToBack(transparentUIView)发送透明UIView对我parentUIView.sendSubviewToBack(transparentUIView) ,因为这样做后UIButton位于视图层次结构的顶部。 Click on the "Debug View Hierarchy" button in Xcode to check if the UIButton is on top or not.单击 Xcode 中的“Debug View Hierarchy”按钮以检查UIButton是否在顶部。

If you're using Autolayout to build your UI, make sure to declare all your constraints in your view and parent views.如果您使用自动布局来构建您的 UI,请确保在您的视图和父视图中声明所有约束

Some times we forget to set all of them and the system complains about it, drawing your UI but not responding correctly in your touch events.有时我们忘记设置所有这些,系统会抱怨它,绘制您的 UI 但在您的触摸事件中没有正确响应。

In my case, i've forgot to set my bottom constraint in my view so i'm here to set this comment as a reminder.就我而言,我忘记在我的视图中设置底部约束,所以我在这里将此评论设置为提醒。

When a view like a button is placed next to another view like an image view etc. especially if if the image view is on top of another view Xcode sometimes thinks that your button is underneath that image view even though it is not.当像按钮这样的视图放置在另一个视图(如图像视图等)旁边时,尤其是如果图像视图位于另一个视图之上时,Xcode 有时会认为您的按钮在该图像视图下方,即使它不是。 Sometimes you need to clear all the constraints and reset all constraints in order for the button to work.有时您需要清除所有约束并重置所有约束才能使按钮起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM