ios Swift 显示警报最佳实践
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29633938/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Swift Displaying Alerts best practices
提问by Ryan Bobrowski
I have various controllers in my app that all require validation, and when validation fails, I want to display an alert with the errors. Is there some best practice/design pattern for doing this? I could simply create a static function in a Helper class like so:
我的应用程序中有各种控制器都需要验证,当验证失败时,我想显示带有错误的警报。是否有一些最佳实践/设计模式可以做到这一点?我可以简单地在 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)
}
But then I need to pass the view controller..which seems like bad practice. I could shoot off a notification and observe it, but that seems like overkill. Am I overthinking this, or is there some more acceptable way to go about handling something like this?
但是后来我需要传递视图控制器......这似乎是不好的做法。我可以发出通知并观察它,但这似乎有点矫枉过正。我是不是想多了,还是有一些更可接受的方法来处理这样的事情?
回答by Ryan Bobrowski
I ended up creating an extension for UIViewController and creating the alert function there:
我最终为 UIViewController 创建了一个扩展并在那里创建了警报功能:
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)
}
}
回答by Sigex
Swift 4
斯威夫特 4
Here you are I wanted this so I made a full extension. So create a new swift file in your project name it what ever you like in side it place the following code.
你来了,我想要这个,所以我做了一个完整的扩展。因此,在您的项目中创建一个新的 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)
}
}
Then to use it which so many people don't actually show which can lead to confusion for a newbie like myself.
然后使用它,很多人实际上并没有展示这可能会导致像我这样的新手感到困惑。
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
}
}
回答by Chris Herbst
As original answer from itstrueimryan at https://stackoverflow.com/a/30714429/6822183
作为来自 itstrueimryan 的原始答案https://stackoverflow.com/a/30714429/6822183
Update for Swift 3:
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)
}
}
回答by Ryan Bobrowski
I may have found a better answer to this problem, via an article by Krakendev: https://krakendev.io/blog/subclassing-can-suck-and-heres-why.
我可能已经通过 Krakendev 的一篇文章找到了这个问题的更好答案:https://krakendev.io/blog/subclassing-can-suck-and-heres-why 。
The idea is to use protocol-oriented programming to create a default implementation of an alert just for UIViewControllers:
这个想法是使用面向协议的编程来为 UIViewControllers 创建一个警报的默认实现:
protocol Alertable {
func issueAlert()
}
extension Alertable where Self: UIViewController {
func issueAlert() {
// alert code here
}
}
Now, just like that, every UIViewController that adheres to Alertable will have the issueAlert() method available to them without even having to define its own implementation.
现在,就像那样,每个遵循 Alertable 的 UIViewController 都可以使用 issueAlert() 方法,甚至不必定义自己的实现。
And, of course, we can define parameters for the issueAlert function as well:
当然,我们也可以为 issueAlert 函数定义参数:
extension Alertable where Self: UIViewController {
func issueAlert(title: "Default Title", message: String = "Default Message") {
// alert code here
}
}
So our view controller can do either:
所以我们的视图控制器可以做到:
issueAlert()
or
或者
issueAlert(title: "Error", message: "Something went wrong")
Two advantages to this approach that I can think of are that you know if a view controller has access to this method just by looking at the Alertable protocol in the class definition, and individual view controllers can override this method if they want to provide custom functionality. Of course, now you can also specify the Alertable contract as a method parameter.
我能想到的这种方法的两个优点是,只需查看类定义中的 Alertable 协议,您就知道视图控制器是否可以访问此方法,并且各个视图控制器如果想提供自定义功能,则可以覆盖此方法. 当然,现在你也可以指定 Alertable 合约作为方法参数。
回答by Kiran jadhav
Updated for swift 3:
为 swift 3 更新:
if you want to show the alert message to user used below simple lines of code;
如果您想在简单的代码行下方向用户显示警报消息;
// function defination:
// 函数定义:
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)
}
//function call :
//函数调用:
self.showMessageToUser(title: "Alert", msg: "your message to user")
// Enjoy coding..!
// 享受编码..!
回答by MobileMon
Why not create a Utility function that returns the AlertView to the ViewController?
为什么不创建一个将 AlertView 返回给 ViewController 的 Utility 函数呢?
self.presentViewController(Utilities.createAlertController("errorMessage"), animated: true, completion: nil);
回答by Maverick2805
I used Sigex's extension in my code, however I have added a check, if options were used or not.
我在我的代码中使用了 Sigex 的扩展,但是我添加了一个检查,是否使用了选项。
If no options are given in the call, then the Alert only shows "OK" and completes with returning option 0.
如果调用中没有给出任何选项,则警报仅显示“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)
}
}
Just omit the part , options: "1","2"
then default alert is shown.
只需省略该部分,, options: "1","2"
然后显示默认警报。
回答by Sazzad Hissain Khan
Answerfrom Sigex is completely fine, except the int
indices passing to trace the button clicks might not make sense because, caller needed to keep track with int value. In that case passing string arguments and comparing them in switch case in completion block
makes more sense to me. I would rather use like,
Sigex 的回答完全没问题,除了int
传递给跟踪按钮点击的索引可能没有意义,因为调用者需要跟踪 int 值。在那种情况下,传递字符串参数并在 switch case 中比较它们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)
}
}
And test with,
并测试,
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
}
}
}
}
回答by Samuel Folledo
I love Sigex's extension, but I spiced it up a bit to add style on button depending on the title
我喜欢 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)
}