Swift 显示警报最佳实践
Swift Displaying Alerts best practices
我的应用程序中有各种控制器都需要验证,当验证失败时,我想显示一个包含错误的警报。是否有一些最好的 practice/design 模式可以做到这一点?我可以简单地在 Helper class 中创建一个静态函数,如下所示:
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)
}
但是我需要传递视图控制器..这似乎是不好的做法。我可以发出通知并观察它,但这似乎有点矫枉过正。我是想多了,还是有一些更可接受的方式来处理这样的事情?
我最终为 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)
}
}
为什么不创建一个 returns AlertView 到 ViewController 的实用函数?
self.presentViewController(Utilities.createAlertController("errorMessage"), animated: true, completion: nil);
来自 itstrueimryan 在
的原始回答
Swift3 的更新:
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)
}
}
我可能已经通过 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")
我能想到的这种方法的两个优点是,您只需查看 class 定义中的 Alertable 协议就可以知道视图控制器是否可以访问此方法,并且各个视图控制器可以覆盖如果他们想提供自定义功能,请使用此方法。当然,现在你也可以将Aertable合约指定为方法参数。
Updated for 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")
// 享受编码..!
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
}
}
我在我的代码中使用了 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"
即可显示默认警报。
来自 Sigex 的 完全没问题,除了传递给跟踪按钮点击的 int
索引可能没有意义,因为调用者需要跟踪 int 值。在那种情况下,传递字符串参数并在 completion block
中的 switch case 中比较它们对我来说更有意义。我宁愿使用 like,
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
}
}
}
}
我喜欢 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)
}
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)
我的应用程序中有各种控制器都需要验证,当验证失败时,我想显示一个包含错误的警报。是否有一些最好的 practice/design 模式可以做到这一点?我可以简单地在 Helper class 中创建一个静态函数,如下所示:
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)
}
但是我需要传递视图控制器..这似乎是不好的做法。我可以发出通知并观察它,但这似乎有点矫枉过正。我是想多了,还是有一些更可接受的方式来处理这样的事情?
我最终为 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)
}
}
为什么不创建一个 returns AlertView 到 ViewController 的实用函数?
self.presentViewController(Utilities.createAlertController("errorMessage"), animated: true, completion: nil);
来自 itstrueimryan 在
Swift3 的更新:
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)
}
}
我可能已经通过 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")
我能想到的这种方法的两个优点是,您只需查看 class 定义中的 Alertable 协议就可以知道视图控制器是否可以访问此方法,并且各个视图控制器可以覆盖如果他们想提供自定义功能,请使用此方法。当然,现在你也可以将Aertable合约指定为方法参数。
Updated for 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")
// 享受编码..!
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
}
}
我在我的代码中使用了 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"
即可显示默认警报。
int
索引可能没有意义,因为调用者需要跟踪 int 值。在那种情况下,传递字符串参数并在 completion block
中的 switch case 中比较它们对我来说更有意义。我宁愿使用 like,
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
}
}
}
}
我喜欢 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)
}
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)