swift - 使用多个按钮自定义警报 View

标签 swift uibutton closures swift4

我正在设计一个自定义的通用警报 View ,如下所示:

警报 View 屏幕截图

Screen Shot

然而,此 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/

相关文章:

python - 嵌套函数中的局部变量

javascript - 使用 browserify 时闭包/模块模式是否已过时?

JavaScript 分隔符和闭包

ios - 打开一个警报,要求选择应用程序打开 map

ios - 带 Lottie 的动态按钮

iOS - 更改 UIButton 或自定义 UIButton 的渐变背景

ios - 如何为 UIButton 的操作设置每小时限制?

ios - 在 Swift 中查看模型绑定(bind)

swift - 构建完美的 Swift 错误

swift - Swift 中两种不同类型的 nil?