我该如何在Swift中创建一个UIAlertView?

555

我一直在努力使用Swift创建UIAlertView,但由于某种原因,我无法正确编写语句,因为我得到了这个错误:

找不到接受提供的参数的“init”重载

以下是我的编写方式:

let button2Alert: UIAlertView = UIAlertView(title: "Title", message: "message",
                     delegate: self, cancelButtonTitle: "OK", otherButtonTitles: nil)

然后我使用以下代码进行调用:

button2Alert.show()

截至目前它正在崩溃,我似乎无法正确地编写语法。


6
iOS 8中已经用UIAlertController替代了UIAlertView和UIActionSheet,你有看过吗?请注意不要改变原意。 - Popeye
请确保self所属的类采用了协议UIAlertViewDelegate(在Swift中,推荐的方法是使用扩展)。 - Nicolas Miari
@Adam:我已经恢复了您的重新标记。[tag:swift3]标签用于与苹果Swift编程语言第三版中的更改直接相关的问题。我认为来自https://meta.stackoverflow.com/questions/252079/tagging-a-question-based-on-its-answers的“If the answers make it clear that the problem in the question was caused by something other than what the asker thought, retagging is very helpful.”并不适用于这里。 - Martin R
1
@MartinR 我不知道如何更新问题以显示有适用于当前版本的Swift的答案;这里有很多旧的、无用的东西,[swift]与有用的东西一起找到了它们。我对这个重新标记被还原并没有强烈的感觉,但我希望有一个明确的方法来解决这个问题。(我希望答案有标签。) - Adam Eberbach
36个回答

998

UIAlertView类:

// UIAlertView已被弃用。请改用带有UIAlertControllerStyleAlert样式的UIAlertController

在iOS 8上,您可以这样做:

let alert = UIAlertController(title: "Alert", message: "Message", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)

现在UIAlertController是一个单一的类,用于在iOS 8上创建和交互我们所知道的UIAlertViewUIActionSheet

编辑:处理操作:

alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: { action in
    switch action.style{
    case .Default:
        print("default")
        
    case .Cancel:
        print("cancel")
        
    case .Destructive:
        print("destructive")
    }
}}))

针对Swift 3的编辑:

let alert = UIAlertController(title: "Alert", message: "Message", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)

针对 Swift 4.x 进行编辑:

let alert = UIAlertController(title: "Alert", message: "Message", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { action in
    switch action.style{
        case .default:
        print("default")
        
        case .cancel:
        print("cancel")
        
        case .destructive:
        print("destructive")
        
    }
}))
self.present(alert, animated: true, completion: nil)

3
你在哪里看到UIAlertView被弃用了?我在文档中没有看到这个信息。 - BlueBear
9
按下 Cmd + 点击 UIAlertView 类,类声明的顶部就是注释。 - Oscar Swanros
5
取消和破坏性案例的意义在于,即使您指定了“Default”,它们也可以提供备选方案。 - User
2
我认为你的例子很令人困惑,或者至少我不理解它的用处。动作的样式已经是“默认”的了。在你的闭包中,没有理由去switch它。它总是会走到默认值。你能否让你的例子更有意义,以便我们知道为什么闭包将action作为参数? - mfaani
5
阅读此答案,你所做的switch case是不必要的。如果类型或标题是硬编码(即它们是动态的),则switch语句只有在这种情况下才有用:您可能拥有一系列动态按钮,因此标题不是硬编码的。然后处理程序可能需要将所选标题传递给某个其他方法调用 - mfaani
显示剩余4条评论

555

一个按钮

一个按钮截图

class ViewController: UIViewController {

    @IBAction func showAlertButtonTapped(_ sender: UIButton) {

        // create the alert
        let alert = UIAlertController(title: "My Title", message: "This is my message.", preferredStyle: UIAlertController.Style.alert)

        // add an action (button)
        alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))

        // show the alert
        self.present(alert, animated: true, completion: nil)
    }
}

两个按钮

“两个按钮”弹窗截图

class ViewController: UIViewController {

    @IBAction func showAlertButtonTapped(_ sender: UIButton) {

        // create the alert
        let alert = UIAlertController(title: "UIAlertController", message: "Would you like to continue learning how to use iOS alerts?", preferredStyle: UIAlertController.Style.alert)

        // add the actions (buttons)
        alert.addAction(UIAlertAction(title: "Continue", style: UIAlertAction.Style.default, handler: nil))
        alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: nil))

        // show the alert
        self.present(alert, animated: true, completion: nil)
    }
}

三个按钮

在这里输入图像描述

class ViewController: UIViewController {

    @IBAction func showAlertButtonTapped(_ sender: UIButton) {

        // create the alert
        let alert = UIAlertController(title: "Notice", message: "Lauching this missile will destroy the entire universe. Is this what you intended to do?", preferredStyle: UIAlertController.Style.alert)

        // add the actions (buttons)
        alert.addAction(UIAlertAction(title: "Remind Me Tomorrow", style: UIAlertAction.Style.default, handler: nil))
        alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: nil))
        alert.addAction(UIAlertAction(title: "Launch the Missile", style: UIAlertAction.Style.destructive, handler: nil))

        // show the alert
        self.present(alert, animated: true, completion: nil)
    }
}

处理按钮点击

在上面的例子中,handlernil。您可以使用闭包代替nil来执行用户点击按钮时的操作。例如:

alert.addAction(UIAlertAction(title: "Launch the Missile", style: UIAlertAction.Style.destructive, handler: { action in

    // do something like...
    self.launchMissile()

}))

笔记

  • 多个按钮不一定需要使用不同的UIAlertAction.Style类型。它们都可以是.default
  • 如果有三个以上的按钮,请考虑使用操作表(Action Sheet)。设置非常类似。 这里提供了一个例子。

2
UIAlertController中是否有任何委托属性?在UIAlertView中,有一个委托属性,有时我们将其设置为self。在UIAlertController中有没有类似的东西?我是新手,请帮帮我。 - ArgaPK
优美的答案 - 现在我们如何在处理程序中切换到新视图? - That1Guy
哇,太棒了。你节省了我的时间。非常感谢你。 - Ganesan J

117

您可以使用标准构造函数创建UIAlert,但是“legacy”构造函数似乎无法正常工作:

let alert = UIAlertView()
alert.title = "Alert"
alert.message = "Here's a message"
alert.addButtonWithTitle("Understood")
alert.show()

9
UIAlertView已经被弃用,请改用preferredStyle为UIAlertControllerStyleAlert的UIAlertController。请注意不要改变原来的意思。 - Zorayr
17
UIAlertController仅从iOS 8及以上版本可用,请在建议使用时提到。仍有需要支持iOS 7的情况,人们可能会忽视这个问题。废弃并不意味着“完全不再使用”。 - Sami Kuhmonen
2
如果您的应用程序仍然针对iOS 7,则此方法有效。但是,理想情况下,只有在UIAlertController不可用时才应使用UIAlertView。如果 NSClassFromString("UIAlertController") != nil { /* 使用UIAlertController / } else { / 使用UIAlertView */ } - phatblat
UIAlertview()在iOS 9中已被弃用。 - Rizwan Ahmed

49

在 Swift 4.2 和 Xcode 10 中

方法1:

简单提示框

let alert = UIAlertController(title: "Your title", message: "Your message", preferredStyle: .alert)
    
     let ok = UIAlertAction(title: "OK", style: .default, handler: { action in
     })
     alert.addAction(ok)
     let cancel = UIAlertAction(title: "Cancel", style: .default, handler: { action in
     })
     alert.addAction(cancel)
     DispatchQueue.main.async(execute: {
        self.present(alert, animated: true)
})

方法2:

共享类警报

如果您想使用共享类样式(编写一次,到处使用)

import UIKit
class SharedClass: NSObject {//This is shared class
static let sharedInstance = SharedClass()

    //Show alert
    func alert(view: UIViewController, title: String, message: String) {
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        let defaultAction = UIAlertAction(title: "OK", style: .default, handler: { action in
        })
        alert.addAction(defaultAction)
        DispatchQueue.main.async(execute: {
            view.present(alert, animated: true)
        })
    }

    private override init() {
    }
}

现在在每个地方调用警报(alert)像这样

SharedClass.sharedInstance.alert(view: self, title: "Your title here", message: "Your message here")

方法三:

在所有窗口上方显示警报

如果您想在所有视图的顶部显示警报,请使用此代码

func alertWindow(title: String, message: String) {
    DispatchQueue.main.async(execute: {
        let alertWindow = UIWindow(frame: UIScreen.main.bounds)
        alertWindow.rootViewController = UIViewController()
        alertWindow.windowLevel = UIWindowLevelAlert + 1
    
        let alert2 = UIAlertController(title: title, message: message, preferredStyle: .alert)
        let defaultAction2 = UIAlertAction(title: "OK", style: .default, handler: { action in
        })
        alert2.addAction(defaultAction2)
    
        alertWindow.makeKeyAndVisible()
    
        alertWindow.rootViewController?.present(alert2, animated: true, completion: nil)
    })
}

函数调用

SharedClass.sharedInstance.alertWindow(title:"This your title", message:"This is your message")

方法四:

使用扩展程序的警告

extension  UIViewController {

    func showAlert(withTitle title: String, withMessage message:String) {
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        let ok = UIAlertAction(title: "OK", style: .default, handler: { action in
        })
        let cancel = UIAlertAction(title: "Cancel", style: .default, handler: { action in
        })
        alert.addAction(ok)
        alert.addAction(cancel)
        DispatchQueue.main.async(execute: {
            self.present(alert, animated: true)
        })
    }
}

现在这样调用

//Call showAlert function in your class
@IBAction func onClickAlert(_ sender: UIButton) {
    showAlert(withTitle:"Your Title Here", withMessage: "YourCustomMessageHere")
}

方法 5:

使用文本框的警告

如果您想要在警告中添加文本框。

//Global variables
var name:String?
var login:String?

//Call this function like this:  alertWithTF() 
//Add textfields to alert 
func alertWithTF() {
    
    let alert = UIAlertController(title: "Login", message: "Enter username&password", preferredStyle: .alert)
    // Login button
    let loginAction = UIAlertAction(title: "Login", style: .default, handler: { (action) -> Void in
        // Get TextFields text
        let usernameTxt = alert.textFields![0]
        let passwordTxt = alert.textFields![1]
        //Asign textfileds text to our global varibles
        self.name = usernameTxt.text
        self.login = passwordTxt.text
        
        print("USERNAME: \(self.name!)\nPASSWORD: \(self.login!)")
    })
    
    // Cancel button
    let cancel = UIAlertAction(title: "Cancel", style: .destructive, handler: { (action) -> Void in })
    
    //1 textField for username
    alert.addTextField { (textField: UITextField) in
        textField.placeholder = "Enter username"
        //If required mention keyboard type, delegates, text sixe and font etc...
        //EX:
        textField.keyboardType = .default
    }
    
    //2nd textField for password
    alert.addTextField { (textField: UITextField) in
        textField.placeholder = "Enter password"
        textField.isSecureTextEntry = true
    }
    
    // Add actions
    alert.addAction(loginAction)
    alert.addAction(cancel)
    self.present(alert, animated: true, completion: nil)
    
}

方法六:

共享类中使用扩展提醒

//This is your shared class
import UIKit

 class SharedClass: NSObject {

 static let sharedInstance = SharedClass()

 //Here write your code....

 private override init() {
 }
}

//Alert function in shared class
extension UIViewController {
    func showAlert(title: String, msg: String) {
        DispatchQueue.main.async {
            let alert = UIAlertController(title: title, message: msg, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
            self.present(alert, animated: true, completion: nil)
        }
    }
}

现在可以直接这样调用

self.showAlert(title: "Your title here...", msg: "Your message here...")

方法七:

在不共享类的情况下使用扩展警报,可以将其放入单独的类中。创建一个新的Swift类,并import UIKit。复制并粘贴以下代码。

//This is your Swift new class file
import UIKit
import Foundation

extension UIAlertController {
    class func alert(title:String, msg:String, target: UIViewController) {
        let alert = UIAlertController(title: title, message: msg, preferredStyle: UIAlertControllerStyle.alert)
        alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default) {
        (result: UIAlertAction) -> Void in
        })
        target.present(alert, animated: true, completion: nil)
    }
}

现在在您所有的类中这样调用alert函数(单行代码)。

UIAlertController.alert(title:"Title", msg:"Message", target: self)

它是如何工作的?


抱歉,我不太理解,请您可以简短地解释一下吗? - Naresh
我需要一个alertController,直到点击“OK”按钮或超时发生才会显示。类似于方法6或7,但具有额外的输入变量“timeout”。 - PascalS
扩展 UIViewController { func alertWithTime(title: String, msg: String, timeInterval: TimeInterval) { DispatchQueue.main.async { let alert = UIAlertController(title: title, message: msg, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default, handler: nil)) self.present(alert, animated: true, completion: nil) if #available(iOS 10.0, *) { Timer.scheduledTimer(withTimeInterval: timeInterval, repeats: false, block: { _ in alert.dismiss(animated: true, completion: nil) }) } else {// 回退到早期版本}}}} - Naresh
1
如果您在timeInterval中提到0,那么如果您不想关闭警报,请使用if条件。if timeInterval!= 0 {                 if#available(iOS 10.0,*){                     Timer.scheduledTimer(withTimeInterval:timeInterval,repeats:false,block:{_ in                         alert.dismiss(animated:true,completion:nil)                     })                 } else {                     //回退到早期版本                 }             } - Naresh
1
不错的解决方案。在第二种方法中,“SharedClass.SharedInstance…”必须更改为“SharedClass.sharedInstance…”。 - ozkulah
显示剩余3条评论

20

点击查看

@IBAction func testClick(sender: UIButton) {

  var uiAlert = UIAlertController(title: "Title", message: "Message", preferredStyle: UIAlertControllerStyle.Alert)
  self.presentViewController(uiAlert, animated: true, completion: nil)

  uiAlert.addAction(UIAlertAction(title: "Ok", style: .Default, handler: { action in
   println("Click of default button")
  }))

  uiAlert.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: { action in
   println("Click of cancel button")
  }))

}

使用两个按钮 OK & Cancel 完成


对我来说非常有帮助。 - Mandeep

12

通过Swift 2的协议扩展,您可以创建一个协议,为您的视图控制器提供默认实现:

ShowsAlert.swift

import UIKit

protocol ShowsAlert {}

extension ShowsAlert where Self: UIViewController {
    func showAlert(title: String = "Error", message: String) {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
        alertController.addAction(UIAlertAction(title: "Ok", style: .Default, handler: nil))
        presentViewController(alertController, animated: true, completion: nil)
    }
}

视图控制器.swift

class ViewController: UIViewController, ShowsAlert {
    override func viewDidLoad() {
        super.viewDidLoad()
        showAlert(message: "Hey there, I am an error message!")
    }
}

1
完美运行。对于Swift3,请将“presentViewController”更改为“present”。 - Vincent

12

如果你的目标是iOS 7 8,你需要像这样做一些事情,以确保你在每个版本中使用正确的方法,因为UIAlertView在iOS 8中已经被废弃,但UIAlertController在iOS7中不可用:

func alert(title: String, message: String) {
    if let getModernAlert: AnyClass = NSClassFromString("UIAlertController") { // iOS 8
        let myAlert: UIAlertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
        myAlert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
        self.presentViewController(myAlert, animated: true, completion: nil)
    } else { // iOS 7
        let alert: UIAlertView = UIAlertView()
        alert.delegate = self

        alert.title = title
        alert.message = message
        alert.addButtonWithTitle("OK")

        alert.show()
    }
}

或者你可以节省时间,直接使用 UIAlertView 直到你不再支持 iOS 7。苹果不会因此拒绝你的应用程序。 - cprcrack
2
弃用并不意味着“不要使用这个”或者说它是“错误的方法”,它只是意味着它将来不会再起作用。如果只需要基本警报,则在iOS8上没有必要专门使用UIAlertController。它们将像以前一样工作。有许多API已经在iOS4或5中被弃用,但仍然在iOS8中工作。但是当然,针对更高的iOS级别的应用程序不应该使用它们,这就是为什么会出现弃用警告的原因。 - Sami Kuhmonen
1
@SamiKuhmonen 不是,但它使你做的事情更清晰,并且在你的最低版本足够高时更容易删除不推荐使用的方法的支持。 - AstroCB

11

在构造函数中不要提供其他选项。

let alertView = UIAlertView(title: "Oops!", message: "Something
happened...", delegate: nil, cancelButtonTitle: "OK")

alertView.show()

但我同意Oscar的观点,在iOS 8中,这个类已经被弃用,所以如果你开发的是一个只支持iOS 8及以上版本的应用程序,就不需要使用UIAlertView了。否则上述代码将能够正常工作。


11

在Swift语言中显示UIAlertView: -

协议UIAlertViewDelegate

let alert = UIAlertView(title: "alertView", message: "This is alertView", delegate:self, cancelButtonTitle:"Cancel", otherButtonTitles: "Done", "Delete")
alert.show()
```

在Swift语言中显示UIAlertViewController:

```
let alert = UIAlertController(title: "Error", message: "Enter data in Text fields", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)

10

对于 SWIFT4 ,我认为,扩展 UIViewController 并创建可重用的确认控件是最优雅的方式。

您可以按如下方式扩展 UIViewController


您可以按如下方式扩展UIViewController

extension UIViewController {

func AskConfirmation (title:String, message:String, completion:@escaping (_ result:Bool) -> Void) {
    let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
    self.present(alert, animated: true, completion: nil)

    alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { action in
        completion(true)
    }))

    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { action in
        completion(false)
    }))
  }
}

那么您随时可以使用它:

 AskConfirmation(title: "YOUR MESSAGE TITLE", message: "YOUR MESSAGE") { (result) in
        if result { //User has clicked on Ok

        } else { //User has clicked on Cancel

        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接