Swift显示警报最佳实践

时间:2015-04-14 17:37:57

标签: ios xcode uialertcontroller

我的应用程序中有各种控制器都需要验证,当验证失败时,我想显示有错误的警报。这样做有一些最佳实践/设计模式吗?我可以简单地在Helper类中创建一个静态函数,如下所示:

static func displayAlert(message: String, buttonTitle: String, vc: UIViewController)
{
    let alertController = UIAlertController(title: "", message: message, preferredStyle: .Alert)

    let OKAction = UIAlertAction(title: buttonTitle, style: .Default, handler: nil)
    alertController.addAction(OKAction)

    vc.presentViewController(alertController, animated: true, completion: nil)
}

但后来我需要传递视图控制器..这似乎是不好的做法。我可以拍摄通知并观察它,但这似乎有点矫枉过正。我是否在思考这个问题,还是有更多可接受的方法来处理这样的事情?

10 个答案:

答案 0 :(得分:48)

我最终为UIViewController创建了一个扩展,并在那里创建了alert函数:

extension UIViewController {

  func alert(message: String, title: String = "") {
    let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
    let OKAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
    alertController.addAction(OKAction)
    self.presentViewController(alertController, animated: true, completion: nil)
  }

}

答案 1 :(得分:19)

Swift 4

在这里,我想要这个,所以我做了一个完整的扩展。因此,在您的项目名称中创建一个新的swift文件,它可以放置以下代码。

import UIKit

extension UIViewController {

    func presentAlertWithTitle(title: String, message: String, options: String..., completion: @escaping (Int) -> Void) {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        for (index, option) in options.enumerated() {
            alertController.addAction(UIAlertAction.init(title: option, style: .default, handler: { (action) in
                completion(index)
            }))
        }
        self.present(alertController, animated: true, completion: nil)
    }
}

然后使用它,这么多人实际上没有显示哪些可能导致像我这样的新手混淆。

presentAlertWithTitle(title: "Test", message: "A message", options: "1", "2") { (option) in
    print("option: \(option)")
    switch(option) {
        case 0:
            print("option one")
            break
        case 1:
            print("option two")
        default:
            break
    }
}

答案 2 :(得分:9)

作为来自itstrueimryan https://stackoverflow.com/a/30714429/6822183

的原始回答

Swift 3更新:

extension UIViewController {

    func alert(message: String, title: String = "") {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil)
        alertController.addAction(OKAction)
        self.present(alertController, animated: true, completion: nil)
    }
}

答案 3 :(得分:2)

我可能通过Krakendev的一篇文章找到了更好的答案:https://krakendev.io/blog/subclassing-can-suck-and-heres-why

我们的想法是使用面向协议的编程为UIViewControllers创建一个警报的默认实现:

protocol Alertable {
    func issueAlert()
}

extension Alertable where Self: UIViewController {
    func issueAlert() {
        // alert code here
    }
}

现在,就像那样,每个遵守Alertable的UIViewController都可以使用issueAlert()方法,甚至无需定义自己的实现。

当然,我们也可以为issueAlert函数定义参数:

extension Alertable where Self: UIViewController {
    func issueAlert(title: "Default Title", message: String = "Default Message") {
        // alert code here
    }
}

所以我们的视图控制器可以执行以下任一操作:

issueAlert()

issueAlert(title: "Error", message: "Something went wrong")

我能想到的这种方法的两个优点是,只要通过查看类定义中的Alertable协议,您就知道视图控制器是否可以访问此方法,并且单个视图控制器可以在需要时覆盖此方法提供自定义功能。当然,现在您也可以将Alertable合约指定为方法参数。

答案 4 :(得分:1)

为什么不创建一个将AlertView返回给ViewController的Utility函数?

self.presentViewController(Utilities.createAlertController("errorMessage"), animated: true, completion: nil);

答案 5 :(得分:1)

  

更新了swift 3:

如果您想在简单的代码行下面向用户显示警告消息;

//功能定义:

func showMessageToUser(title: String, msg: String)  {
    let alert = UIAlertController(title: title, message: msg, preferredStyle: UIAlertControllerStyle.alert)
    alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil))
    self.present(alert, animated: true, completion: nil)
}

//函数调用:

self.showMessageToUser(title: "Alert", msg: "your message to user")

//享受编码..!

答案 6 :(得分:1)

我在代码中使用了Sigex的扩展名,但是我添加了一项检查(是否使用了选项)。

如果呼叫中未提供任何选项,则警报仅显示“ OK”,并以返回选项0结束。

extension UIViewController {

    func presentAlertWithTitle(title: String, message: String, options: String..., completion: @escaping (Int) -> Void) {

        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        if options.count == 0 {
            let OKAction = UIAlertAction(title: "OK", style: .default, handler: { (action) in
                 completion(0)
            })
            alertController.addAction(OKAction)
        } else {

            for (index, option) in options.enumerated() {
                 alertController.addAction(UIAlertAction.init(title: option, style: .default, handler: { (action) in
                    completion(index)
                }))
            }
        }
        self.present(alertController, animated: true, completion: nil)
    }

}

只需省略, options: "1","2"部分,然后显示默认警报。

答案 7 :(得分:0)

来自Sigex的

Answer很好,除了传递int索引以跟踪按钮单击可能没有意义,因为调用者需要跟踪int值。在那种情况下,传递字符串参数并在completion block中以切换大小写比较它们对我来说更有意义。我宁愿使用,

import UIKit

extension UIViewController {

    func presentAlertWithTitle(title: String, message: String, options: String..., completion: @escaping (String) -> Void) {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        for (index, option) in options.enumerated() {
            alertController.addAction(UIAlertAction.init(title: option, style: .default, handler: { (action) in
                completion(options[index])
            }))
        }
        self.present(alertController, animated: true, completion: nil)
    }
}

并进行测试,

class TestViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        presentAlertWithTitle(title: "Test", message: "A sample message", options: "start", "stop", "cancel") { (option) in
            print("option: \(option)")
            switch(option) {
                case "start":
                    print("start button pressed")
                    break
                case "stop":
                    print("stop button pressed")
                    break
                case "cancel":
                    print("cancel button pressed")
                    break
                default:
                    break
            }
        }
    }
}

答案 8 :(得分:0)

我喜欢Sigex的扩展名,但是我对它进行了一些修改,以便根据标题添加按钮上的样式

func presentAlertWithOptions(title: String, message: String, options: String..., completion: @escaping (Int) -> Void) {
    let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
    if options.count == 0 { //if there is no options, show a basic alert
        let OKAction = UIAlertAction(title: "OK", style: .default, handler: { (action) in
             completion(0)
        })
        alertController.addAction(OKAction)
    } else { //alert with options
        for (index, option) in options.enumerated() {
            var alertStyle = UIAlertAction.Style.default
            switch option { //check if we should style the buttons
            case "Cancel": //cancel style
                alertStyle = .cancel
            case "Logout", "Discard Changes", "Discard", "Delete", "Remove": //destructive style
                alertStyle = .destructive
            default: break //keep as default
            }
            alertController.addAction(UIAlertAction(title: option, style: alertStyle, handler: { (action) in
                completion(index)
            }))
        }
    }
    self.present(alertController, animated: true, completion: nil)
}

答案 9 :(得分:0)

Swift 4.1

    let alert = UIAlertController(title: "Atenção",message: "Mensagem Aqui",preferredStyle: .alert)

    alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
    self.present(alert, animated: true)