UIButton 在 UIWindow 的子视图上不起作用
Posted
技术标签:
【中文标题】UIButton 在 UIWindow 的子视图上不起作用【英文标题】:UIButton not working on a subview of UIWindow 【发布时间】:2016-08-05 17:47:30 【问题描述】:我正在尝试在 Swift 中创建一个自定义的一键式 AlertViewController,我使用 window.addSubview() 来显示 AlertView,但是当触摸 AlertView 上的按钮时,func buttonTapped() 不起作用,下面是我的代码,请告诉我这里出了什么问题,谢谢。
MyAlertViewController.swift
class MyAlertViewController: UIViewController
var button: UIButton!
var contentView: UIView!
override func viewDidLoad()
super.viewDidLoad()
setUp()
func setUp()
contentView = UIView(frame: CGRectMake(0,0,200,300))
contentView.center = view.center
contentView.backgroundColor = UIColor.whiteColor()
contentView.layer.cornerRadius = 10
button = UIButton(type: .System)
button.frame = CGRectMake(50, 150, 100, 40)
button.setTitle("button", forState: UIControlState.Normal)
button.addTarget(self, action: #selector(buttonTapped(_:)), forControlEvents: UIControlEvents.TouchUpInside)
view.addSubview(contentView)
contentView.addSubview(button)
view.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.1)
view.userInteractionEnabled = true
func buttonTapped(sender: AnyObject?)
print("button tapped")
func show()
let window = UIApplication.sharedApplication().keyWindow! as UIWindow
view.frame = window.bounds
window.addSubview(view)
ParentViewController.swift(是我窗口的rootViewController)
class ParentViewController: UIViewController
var button: UIButton!
override func viewDidLoad()
super.viewDidLoad()
view.backgroundColor = UIColor.whiteColor()
button = UIButton(type: .System)
button.frame = CGRectMake(110,269,100,30)
button.setTitle("show", forState: .Normal)
button.addTarget(self, action: #selector(buttonTapped(_:)), forControlEvents: .TouchUpInside)
view.addSubview(button)
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
func buttonTapped(sender: AnyObject?)
MyAlertViewController().show()
我发现如果我更改 ParentViewController.swift 如下,警报视图上的按钮可以正常工作。
class ParentViewController: UIViewController
var button: UIButton!
var vc: MyAlertViewController!
override func viewDidLoad()
super.viewDidLoad()
view.backgroundColor = UIColor.cyanColor()
button = UIButton(type: .System)
button.frame = CGRectMake(110,269,100,30)
button.setTitle("show", forState: .Normal)
button.addTarget(self, action: #selector(buttonTapped(_:)), forControlEvents: .TouchUpInside)
view.addSubview(button)
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
func buttonTapped(sender: AnyObject?)
vc = MyAlertViewController()
vc.show()
但是我打算在每次用户收到新消息时显示这个警报视图,所以它会随时出现在任何 ViewController 上,所以我不想在每个 ViewController 中声明它,所以我该如何解决这个?
【问题讨论】:
【参考方案1】:TLDR;
您必须保留 MyAlertViewController() 的一个实例。
改成这个,它会起作用(就像你已经做的那样):
// keep some reference
var alert: MyAlertViewController?
func buttonTapped(sender: AnyObject?)
alert = MyAlertViewController()
alert?.show()
更多解释
在 MyAlertViewController 中调用的button.addTarget(self, ...)
不保留self
。
addTarget
函数的文档最后一行说:
// ...动作不能为NULL。请注意,目标不保留。*
因此,离开此功能后将不会有self
发送操作:
func buttonTapped(sender: AnyObject?)
MyAlertViewController().show()
另一种选择,
是在 MyAlertViewController 中保留self
变量:
// retain self manually
var mySelf: MyAlertViewController?
func setUp()
...
// reference to self
mySelf = self
button.addTarget(mySelf, action: #selector(buttonTapped(_:)), forControlEvents: UIControlEvents.TouchUpInside)
【讨论】:
谢谢,所以 MyAlertViewController().show() 没有创建对 MyAlertViewController 实例的强引用? @Keater 是的。所以这行 button.addTarget... 基本上什么都不做。 非常感谢.. . 谢谢,它在类似的情况下帮助了我以上是关于UIButton 在 UIWindow 的子视图上不起作用的主要内容,如果未能解决你的问题,请参考以下文章
将 UIView 添加到 UIWindow 的子视图时未检测到画外音
来自 UIWindow 的子视图并将其发送回 UIwindow
作为 UIWindow 子视图添加的 UIView 不响应点击
UIWindow 在 addSubview 之后不更新子视图