我正在设计一个自定义的通用警报 View ,如下所示:
警报 View 屏幕截图
然而,此 View 中的 2 个按钮始终执行相同的操作。
它始终为两个按钮执行下面的第二行代码。
optionAlertVC.btn_ok.actionHandle(controlEvents: .touchUpInside, ForAction: ok)
optionAlertVC.btn_cancel.actionHandle(controlEvents: .touchUpInside, ForAction: cancel)
显示一些代码来帮助我解决这个问题。
View Controller :
func logout() {
AlertManager.shared.showAlertWithTwoOptions(viewController: self, message: "Confirm to logout?", okTitle: "Log out", dismissTitle: "Cancel", ok: {
self.gotoLogin()
}, cancel: {
//nothing to do
}, title: "Logout")
}
警报管理器:
typealias ok = () -> Void
typealias cancel = () -> Void
func showAlertWithTwoOptions(viewController: UIViewController, message: String, okTitle: String, dismissTitle:String, ok: @escaping ok , cancel: @escaping cancel, title:String? = nil) {
guard let optionAlertVC = Bundle.main.loadNibNamed("AlertView", owner: nil, options: nil)?[1] as? OptionAlertVC else {
print("error in loading error alert")
return
}
optionAlertVC.lbl_title.text = title ?? "Warning"
optionAlertVC.lbl_message.text = message
optionAlertVC.iv_icon.image = UIImage(named: "icon_warning")
optionAlertVC.btn_ok.backgroundColor = UIColor.MyTheme.greenSuccess
optionAlertVC.btn_ok.setTitle(okTitle, for: .normal)
optionAlertVC.btn_ok.titleLabel!.adjustsFontSizeToFitWidth = true
optionAlertVC.btn_cancel.backgroundColor = UIColor.MyTheme.redWarning
optionAlertVC.btn_cancel.setTitle(dismissTitle, for: .normal)
optionAlertVC.btn_cancel.titleLabel!.adjustsFontSizeToFitWidth = true
optionAlertVC.btn_cancel.titleLabel?.numberOfLines = 1
optionAlertVC.btn_ok.actionHandle(controlEvents: .touchUpInside, ForAction: ok)
optionAlertVC.btn_cancel.actionHandle(controlEvents: .touchUpInside, ForAction: cancel)
viewController.present(optionAlertVC, animated: true, completion: nil)
}
UIButtonExtension:
extension UIButton {
fileprivate func actionHandleBlock(action:(() -> Void)? = nil) {
struct __ {
static var action :(() -> Void)?
}
if action != nil {
__.action = action
} else {
__.action?()
}
}
@objc private func triggerActionHandleBlock() {
self.actionHandleBlock()
}
func actionHandle(controlEvents control :UIControl.Event, ForAction action:@escaping () -> Void) {
self.actionHandleBlock(action: action)
self.addTarget(self, action: #selector(UIButton.triggerActionHandleBlock), for: control)
}
}
最佳答案
首先,您不应该以这种方式处理 button
触摸。其次,您将 struct
命名得很糟糕。如果我必须对那个 struct
说些什么,那么我应该如何命名它,以便您知道我在谈论那个 struct
?
谈到实际问题,当您使用 static
处理某些内容时,有时会变得棘手。当您在 struct ___ 上声明一个
,无论你有多少个按钮,它总是会调用最新的按钮回调(即一个static
var action
(即 static var action :(() -> Void)?
) 闭包
),因为它不是一个可以保持回调的数组
所有按钮的操作,它只有一个变量,因此它将继续用最新的回调覆盖以前的 button
回调。我认为您应该删除 UIButton
的这个扩展实现,因为它会继续导致不必要的问题。
您实际上不需要做任何额外的事情来处理 UIButton
触摸。只需为每个按钮声明单独的方法,并在添加目标时告诉按钮该方法,如下所示,
class OptionAlertVC: UIViewController {
var btn_ok: UIButton!
var btn_cancel: UIButton!
public var okCallback: (() -> Void)?
public var cancelCallback: (() -> Void)?
override func viewDidLoad() {
super.viewDidLoad()
btn_ok.addTarget(self, action: #selector(okAction), for: .touchUpInside)
btn_cancel.addTarget(self, action: #selector(cancelAction), for: .touchUpInside)
}
@objc func okAction() {
okCallback?()
}
@objc func cancelAction() {
cancelCallback?()
}
}
现在,在 showAlertWithTwoOptions
中,您可以删除以下行,
optionAlertVC.btn_ok.actionHandle(controlEvents: .touchUpInside, ForAction: ok)
optionAlertVC.btn_cancel.actionHandle(controlEvents: .touchUpInside, ForAction: cancel)
相反,将回调设置为这样,
optionAlertVC.okCallback = ok
optionAlertVC.cancelCallback = cancel
关于swift - 使用多个按钮自定义警报 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53862171/