如果需要处理函数,则无法将 alertController 移动到 UIViewController 扩展

Unable to move alertController to UIViewController extension, if it requires handler function

在我的整个程序中,我多次调用 UIAlertControllers。为了让事情更容易阅读,如果 AlertController 只有一个 "OK" 动作且 nil 作为处理程序,我就能够成功地分解它。

如果我想传递一个我想 link 作为 UIAlertAction 的函数,我正在努力做同样的事情。 func showOKCancelAlertController 不编译

showOKAlertController(title: "Network Error", message: "Unable to download photos") //This is an example of how I call Alert Controller throughout my code.

extension UIViewController {
    func showOKAlertController(title: String, message: String){
        let myAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        myAlertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
        present(myAlertController, animated: true)
    }

    func showOKCancelAlertController(title: String, message: String, okFunction: UIAlertAction ){
        let myAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        myAlertController.addAction(UIAlertAction(title: "OK", style: .default, handler: okFunction))
        myAlertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
        present(myAlertController, animated: true)
    }
} 

处理程序预期类型是 ((UIAlertAction) -> Swift.Void)? 而不是 UIAlertAction

将您的代码更新为

func showOKCancelAlertController(title: String, message: String, okFunction: ((UIAlertAction) -> Swift.Void)? ){
     let myAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
     myAlertController.addAction(UIAlertAction(title: "OK", style: .default, handler: okFunction))
     myAlertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
     present(myAlertController, animated: true)
}

可能是

extension UIViewController { 
    func showOKAlertController(title: String, message: String,ok:@escaping(() -> ())) {
        let myAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        myAlertController.addAction(UIAlertAction(title: "ok", style: .default, handler: { (al) in
            ok()
        }))
        myAlertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
        present(myAlertController, animated: true)
    }
}

showOKAlertController(title: "This is title", message: "this is message") {
   print("ok")
}

显然,您面临的错误是:

Cannot convert value of type 'UIAlertAction' to expected argument type '((UIAlertAction) -> Void)?'

那是因为 okFunction 类型 UIAlertAction 的参数,这是不正确的部分。您应该让 okFunction 成为 ((UIAlertAction) -> Void)? 类型:

func showOKCancelAlertController(title: String, message: String, okFunction: ((UIAlertAction) -> Void)?) {
    let myAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
    myAlertController.addAction(UIAlertAction(title: "OK", style: .default, handler: okFunction))
    myAlertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
    present(myAlertController, animated: true)
}

那是因为 UIAlertAction 初始化签名是:

init(title: String?, style: UIAlertAction.Style, handler: ((UIAlertAction) -> Void)? = nil),

handler 参数需要 ((UIAlertAction) -> Void)?

因此,您称它为:

showOKCancelAlertController(title: "title", message: "message") { _ in
    print("here is what to do when tapping the OK button")
}

此外,如果“确定”按钮没有任何操作,您可以为 okFunction 参数提供默认 nil 值:

func showOKCancelAlertController(title: String, message: String, okFunction: ((UIAlertAction) -> Void)? = nil)

并将其命名为:

showOKCancelAlertController(title: "title", message: "message")

实际上,这对您的情况来说是一件很酷的事情:此时您甚至不需要实现两种不同的方法,您可以只实现一种方法并传递 okFunction 参数仅在需要时才使用它!示例:

func showAlertController(title: String, message: String, okFunction: ((UIAlertAction) -> Void)? = nil) {
    let myAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
    myAlertController.addAction(UIAlertAction(title: "OK", style: .default, handler: okFunction))
    if let okFun = okFunction {
        myAlertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: okFun))
    }

    present(myAlertController, animated: true)
}

如果要一键显示:

showAlertController(title: "title", message: "message")

以及两个按钮:

showAlertController(title: "title", message: "message") { _ in
    // ...
}

按照我的方式改进你的代码

这可以灵活处理完成处理程序

extension UIViewController {
    func showOKAlertController(title: String, message: String? = nil, okCompletion: @escaping (() -> ()) = {}, presentCompletion: @escaping (() -> ()) = {}) {
        let myAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        let okAction = UIAlertAction(title: "OK", style: .default) { (action: UIAlertAction) in
            okCompletion()
        }
        myAlertController.addAction(okAction)
        DispatchQueue.main.async {
            self.present(alertController, animated: true) {
                presentCompletion()
            }
        }
    }

    func showOKCancelAlertController(title: String, message: String? = nil, okCompletion: @escaping (() -> ()) = {}, cancelCompletion: @escaping (() -> ()) = {}, presentCompletion: @escaping (() -> ()) = {}) {
        let myAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        let okAction = UIAlertAction(title: "OK", style: .default) { (action: UIAlertAction) in
            okCompletion()
        }
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (cancel: UIAlertAction) in
            cancelCompletion()
        }
        myAlertController.addAction(okAction)
        myAlertController.addAction(cancelAction)
        DispatchQueue.main.async {
            self.present(alertController, animated: true) {
                presentCompletion()
            }
        }
    }
}

showOKAlertController(title: "message")

showOKAlertController(title: "message", message: "message")

showOKCancelAlertController(title: "message", message: nil, okCompletion: {
    // ok completion handling
}) {
    // present completion handling
}

或者你可以从我的 gist

中参考上面有用的内容