【发布时间】:2019-01-07 23:49:09
【问题描述】:
下面的代码可以正常编译,但会因unrecognized selector sent to instance 错误而崩溃。
我有一个继承自 UIViewController 的类:
class Controller: UIViewController {
override func viewDidLoad() {
let toolbarWrapper = CustomToolbarWrapper(view: view, target: self)
let toolbar = toolbarWrapper.toolbarView
view.addSubview(toolbar)
... Other code ...
}
}
还有另一个类,它只是 UIView 的包装器并包含按钮:
class CustomToolbarWrapper {
var toolbarView: UIView
init(view: UIView, target: Any) {
let height: CGFloat = 80
toolbarView = UIView(frame: CGRect(x: 0, y: view.frame.height - height, width: view.frame.width, height: height))
let button = UIButton()
... Some button layout code ...
button.addTarget(target, action: #selector(CustomToolbar.buttonTapped(_:)), for: .touchUpInside)
toolbarView.addSubview(button)
}
@objc static func buttonTapped(_ sender: Any) {
print("button tapped")
}
}
为了清楚起见,我省略了一大段代码并保留了我认为必要的部分。我认为我的代码不起作用,因为我误解了目标在 addTarget 函数中的工作方式。通常,我只会使用self 作为按钮操作的目标,所以我只是尝试将self 从视图控制器传递给CustomToolbarWrapper 的init 函数。
我还尝试了什么:
将按钮的目标从target 更改为self,如下所示:
button.addTarget(self, action: #selector(CustomToolbar.buttonTapped(_:)), for: .touchUpInside)
导致应用不再崩溃。然而,相反,我认为这行代码无法执行任何操作(由于某种原因不会引发错误?),因为尝试打印 button.allTargets 甚至 button.allTargets.count 会导致应用程序在编译时崩溃,并且EXC_BREAKPOINT 错误并且在控制台或 XCode UI 中没有错误描述(这让我更加困惑,因为我的代码中没有断点!)。
此外,将buttonPressed(_:) 设为非静态不会改变前面提到的任何观察结果。
另外,为了确保按钮实际上可以交互,我在Controller 的viewDidLoad() 中添加了这个:
for subview in toolbar.subviews? {
if let button = subview as? UIButton {
button.addTarget(self, action: #selector(buttonPressed(_:)), for: .touchUpInside)
}
}
并在Controller 中为按钮添加了一个简单的测试方法:
@objc func buttonPressed(_ sender: UIButton) {
print("Button Pressed")
}
运行代码确实会在控制台日志中打印“Button Pressed”,因此用户应该能够与该按钮进行交互。
如果您认为这不足以解决问题,请随时告诉我,我会发布更多详细信息。
编辑
我更喜欢将按钮操作的实现保留在 CustomToolbarWrapper 类中,以防止将来重复代码,因为无论在哪里创建 CustomToolbarWrapper 的实例,操作都是相同的。
【问题讨论】:
标签: ios swift uikit target-action