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 = true
和UIButton.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 触摸事件