how to pass function in parameter using closure in swift 5 [closed] - ios

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I am new in swift. I have made generic actionsheet
import Foundation
extension UIAlertController{
func action(mes:String,tit:String,tit2:String,operation1:(),operation2:()) {
let actionSheet = UIAlertController(title: "", message:mes, preferredStyle: .actionSheet)
let EButton = UIAlertAction(title:tit ,
style: .default,
handler: { _ in
operation1
})
let AllEButton = UIAlertAction(title:tit2,
style: .default ,
handler:{ _ in
operation2
})
let cancelAction = UIAlertAction(title: "Cancel",
style: .cancel,
handler: nil)
[EButton, AllEButton, cancelAction].forEach { $0.setValue(UIColor.red, forKey: "titleTextColor")
}
actionSheet.addAction(EButton)
actionSheet.addAction(AllEButton)
actionSheet.addAction(cancelAction)
present(actionSheet, animated: true, completion: nil)
}
}
I want to want to call this extension from viewControllerA
let actionView = UIAlertController()
class viewControllerA: UIViewController {}
private extension viewControllerA {
func alertBottomSheat() {
actionView.action(mes: "Update",tit: "Update only",tit2: "Update All", operation1:saveEvent(),operation2:saveEvent())
}
#IBAction func deleteEventButtonClicked(_ sender: Any) {
actionView.action(mes: "delete ",tit: "Delete only",tit2: "Delete All ",operation1:deleteEvent(),operation2:deleteEvent(deleteAll: true))
}
}
Q1- I this right way to call the extension from viewControllerA extension?
Q2- please tell me how to pass function in action function parameter using closure in this line?
actionView.action(mes: "delete ",tit: "Delete only",tit2: "Delete All ",operation1:deleteEvent(),operation2:deleteEvent(deleteAll: true))
and how to use closure in handler of action sheet in this line
let EButton = UIAlertAction(title:tit ,
style: .default,
handler: { _ in
operation1
})

You first need to create an extension for UIViewController instead of UIAlertController
Also, set the correct closure argument for the function and then call the function like this.
extension UIViewController {
func action(message: String, firstTitle: String, secondTitle: String, firstAction: (() -> Void)? = nil, secondAction: (() -> Void)? = nil) {
let actionSheet = UIAlertController(title: "", message: message, preferredStyle: .actionSheet)
let eButton = UIAlertAction(title: firstTitle ,
style: .default,
handler: {_ in firstAction?()})
let allEButton = UIAlertAction(title: secondTitle,
style: .default ,
handler: {_ in secondAction?()})
let cancelAction = UIAlertAction(title: "Cancel",
style: .cancel,
handler: nil)
[eButton, allEButton, cancelAction].forEach { $0.setValue(UIColor.red, forKey: "titleTextColor")}
actionSheet.addAction(eButton)
actionSheet.addAction(allEButton)
actionSheet.addAction(cancelAction)
present(actionSheet, animated: true, completion: nil)
}
}
Usage
private extension viewControllerA {
func alertBottomSheat() {
self.action(message: "Update", firstTitle: "Update only", secondTitle: "Update All", firstAction: saveEvent, secondAction: saveEvent)
}
#IBAction func deleteEventButtonClicked(_ sender: Any) {
self.action(message: "delete ", firstTitle: "Delete only", secondTitle: "Delete All ", firstAction: { self.deleteEvent()}, secondAction: { self.deleteEvent(deleteAll: true) })
}
func saveEvent() {
}
func deleteEvent(deleteAll: Bool = false) {
}
}
Note: Fixed coding standard rule and var names.

Related

UILabel text not updating inside For loop execution Swift [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I am trying to implement based on ActionSheet button click to show selected button title on main viewcontroller UILabel. Here, below code I am using but the label title not updating based on actionsheet button click.
The issue happening by for loop execution. UILabel.text not changing before last For Loop execution. how to handle and fix it?
ActionSheet
#IBAction func ClickAction(_ sender: Any) {
let actionSheetAlertController: UIAlertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
for title in self.titleData {
let action = UIAlertAction(title: title.status, style: .default) { (action) in
print("Title: \(title.status)")
print("Title: \(title.id)")
self.resultTitle.text = title.status // not updating here.
let icon = UIImage.init(named: title.icon)
action.setValue(icon, forKey: "image")
action.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
actionSheetAlertController.addAction(action)
}
let cancelActionButton = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
actionSheetAlertController.addAction(cancelActionButton)
self.present(actionSheetAlertController, animated: true, completion: nil)
}
Getting Output
Your issue not occured in my machine. Please restart your machine, maybe problem will resolve.
You need to make the checks with action title not with the id. So, here is you solution that is working fine:
struct ActionOption {
var id: String
var title: String
var icon: UIImage?
static func getAll() -> [ActionOption] {
let titleData = ["Red", "Green", "Yellow"]
var all: [ActionOption] = []
for (idx, ttl) in titleData.enumerated() {
all.append(ActionOption(id: "\(idx)", title: ttl, icon: nil))
}
return all
}
}
class ViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
var titleData: [ActionOption] = []
override func viewDidLoad() {
super.viewDidLoad()
self.titleData = ActionOption.getAll()
}
#IBAction func changeAction(_ sender: Any) {
let actionSheetAlertController: UIAlertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
for title in self.titleData {
let action = UIAlertAction(title: title.title, style: .default) { (action) in
switch (action.title ?? "") { // you need to vhange your code here
case "Red" :
self.imageView.backgroundColor = UIColor.red
case "Green" :
self.imageView.backgroundColor = UIColor.green
case "Yellow" :
self.imageView.backgroundColor = UIColor.yellow
default : self.imageView.backgroundColor = UIColor.black
}
}
action.setValue(title.icon, forKey: "image")
action.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
actionSheetAlertController.addAction(action)
}
let cancelActionButton = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
actionSheetAlertController.addAction(cancelActionButton)
self.present(actionSheetAlertController, animated: true, completion: nil)
}
}
You need to make some changes in you switch statement, use the parameter closure for deciding the desired action to perform. As these closure will call when the action being perform and that time title for loop object will not be present/available for being used.
Result As of Code:
Just put self.resultTitle.text = title.status inside DispatchQueue.main.async { }
#IBAction func ClickAction(_ sender: Any) {
let actionSheetAlertController: UIAlertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
for title in self.titleData { // I thik this is the plm
let action = UIAlertAction(title: title.status, style: .default) { (action) in
print("Title: \(title.status)")
print("Title: \(title.id)")
DispatchQueue.main.async {
self.resultTitle.text = title.status
}
}
let icon = UIImage.init(named: title.icon)
action.setValue(icon, forKey: "image")
action.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
actionSheetAlertController.addAction(action)
}
let cancelActionButton = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
actionSheetAlertController.addAction(cancelActionButton)
self.present(actionSheetAlertController, animated: true, completion: nil)
}

Passing the function of the UIAlertAction to the UIAlertController extension

I want to have a base UIAlertController and I want to use it in different classes by just passing the buttons and their closures. To achieve this, I created an extension from UIAlertController like below:
extension UIAlertController {
func showAlert(buttons: [ButtonsAction]?) -> UIAlertController {
let alert = self
guard let alertButtons = buttons else {
return alert
}
for button in alertButtons {
let alertAction = UIAlertAction(title: button.title, style: button.style, handler: {action in
button.handler()
})
alert.addAction(alertAction)
}
return alert
}
}
for my buttons I have a struct:
struct ButtonsAction {
let title: String!
let style: UIAlertAction.Style
let handler: () -> Void
}
In one of my viewControllers I have a function which shows the alert. In that function I have a title and a message then I want to have 1 button to dismiss the alert. The function is something like this:
func fetchFaild(title: String, message: String) {
let buttons = ButtonsAction.init(title: "cancel", style: .cancel, handler: {action in
//here I want to dissmiss the alert I dont know how
})
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert).showAlert(buttons: buttons)
alert.show(self, sender: nil)
}
I have problem adding buttons to the Alert and I don't know how to add actions to the buttons.
I know this is not the best practice here. If any one knows any example or any tutorial that can help me achieve this I really appreciate it.
An extension of UIViewController might be a more reasonable solution and the ButtonsAction struct seems to be redundant.
extension UIViewController {
func showAlert(title: String, message: String, actions: [UIAlertAction], completion: (() -> Void)? = nil) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
actions.forEach{alertController.addAction($0)}
self.present(alertController, animated: true, completion: completion)
}
}
class MyController : UIViewController {
func fetchFailed(title: String, message: String) {
let actions = [UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) in
print("Cancel tapped")
})]
showAlert(title: title, message: message, actions: actions)
}
}

How to display an Alert from a different class

I created a Utilities class to hold some common functions, one of which is an alertUser function that if called, will display an Alert box to the user with the provided title and message text. In another class file, I am validating some text field entries and if the validation doesn't pass, then I want to use the alertUser function from the Utilities class. However, when I do this, I get the following error message in the Xcode log:
Warning: Attempt to present <UIAlertController: 0x7f9c4be0b140> on <MyAppName.Utilities: 0x7f9c4be1cb60> whose view is not in the window hierarchy!
The calling code is in a UIViewController class file. Here's the code which is in the
class ItemSettingsVC: UIViewController:
private func validateNameField() -> Bool {
var passed = false
if (nameField.hasText) {
passed = true
} else {
Utilities().alertUser(strTitle: "Alert", strMessage: strInvalidNameFieldErrorMsg)
passed = false
}
return passed
}
Here's the alertUser function which is in the
class Utilities: UIViewController:
public func alertUser(strTitle: String, strMessage: String) {
let myAlert = UIAlertController(title: strTitle, message: strMessage, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)
myAlert.addAction(okAction)
self.present(myAlert, animated: true, completion: nil)
}
This is running on iOS. I'm using Xcode 8 and swift 3. Any help is greatly appreciated. Thanks.
This should do it:
public func alertUser(strTitle: String, strMessage: String) {
let myAlert = UIAlertController(title: strTitle, message: strMessage, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)
myAlert.addAction(okAction)
UIApplication.shared.delegate?.window??.rootViewController?.present(myAlert, animated: true, completion: nil)
}
You have to add an additional parameter in your alertUser function, which would be the VC that will present the alert controller.
for example:
public func alertUser(strTitle: String, strMessage: String, viewController: UIViewController) {
let myAlert = UIAlertController(title: strTitle, message: strMessage, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)
myAlert.addAction(okAction)
viewController.present(myAlert, animated: true, completion: nil)
}
But I would recommend that you just make an extension of UIViewController and add your func alertUser()* there because you would surely use this alertUser in different VCs and complexity wise in my opinion, this would be more optimized.
Like this:
extension UIViewController {
func showAlert(title: String, message: String, callback: #escaping () -> ()) {
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: {
alertAction in
callback()
}))
self.present(alert, animated: true, completion: nil)
}
//add additional functions here if necessary
//like a function showing alert with cancel
}
NOTE : Please don't make your Utilities class a subclass of UIViewController, it would also be better to make it a struct handling static functions and/or variables
Use this class for easy to show Alert or ActionSheet
UIAlertController Extension
public extension UIAlertController {
public func showAlert(animated: Bool = true, completionHandler: (() -> Void)? = nil) {
guard let rootVC = UIApplication.shared.keyWindow?.rootViewController else {
return
}
var forefrontVC = rootVC
while let presentedVC = forefrontVC.presentedViewController {
forefrontVC = presentedVC
}
forefrontVC.present(self, animated: animated, completion: completionHandler)
}
}
AppAlert Class Create For UIAlertController Show
public class AppAlert {
private var alertController: UIAlertController
public init(title: String? = nil, message: String? = nil, preferredStyle: UIAlertControllerStyle) {
self.alertController = UIAlertController(title: title, message: message, preferredStyle: preferredStyle)
}
public func setTitle(_ title: String) -> Self {
alertController.title = title
return self
}
public func setMessage(_ message: String) -> Self {
alertController.message = message
return self
}
public func setPopoverPresentationProperties(sourceView: UIView? = nil, sourceRect:CGRect? = nil, barButtonItem: UIBarButtonItem? = nil, permittedArrowDirections: UIPopoverArrowDirection? = nil) -> Self {
if let poc = alertController.popoverPresentationController {
if let view = sourceView {
poc.sourceView = view
}
if let rect = sourceRect {
poc.sourceRect = rect
}
if let item = barButtonItem {
poc.barButtonItem = item
}
if let directions = permittedArrowDirections {
poc.permittedArrowDirections = directions
}
}
return self
}
public func addAction(title: String = "", style: UIAlertActionStyle = .default, handler: #escaping ((UIAlertAction!) -> Void) = { _ in }) -> Self {
alertController.addAction(UIAlertAction(title: title, style: style, handler: handler))
return self
}
public func addTextFieldHandler(_ handler: #escaping ((UITextField!) -> Void) = { _ in }) -> Self {
alertController.addTextField(configurationHandler: handler)
return self
}
public func build() -> UIAlertController {
return alertController
}
}
Used For Open AlertBox
AppAlert(title: "Question", message: "Are you sure?", preferredStyle: .alert)
.addAction(title: "NO", style: .cancel) { _ in
// action
}
.addAction(title: "Okay", style: .default) { _ in
// action
}
.build()
.showAlert(animated: true)
Used For ActionSheet Open
if UIDevice.current.userInterfaceIdiom != .pad {
// Sample to show on iPhone
AppAlert(title: "Question", message: "Are you sure?", preferredStyle: .actionSheet)
.addAction(title: "NO", style: .cancel) {_ in
print("No")
}
.addAction(title: "YES", style: .default) { _ in
print("Yes")
}
.build()
.showAlert(animated: true)
} else {
// Sample to show on iPad
AppAlert(title: "Question", message: "Are you sure?", preferredStyle: .actionSheet)
.addAction(title: "Not Sure", style: .default) {
_ in
print("No")
}
.addAction(title: "YES", style: .default) { _ in
print("Yes")
}
.setPopoverPresentationProperties(sourceView: self, sourceRect: CGRect.init(x: 0, y: 0, width: 100, height: 100), barButtonItem: nil, permittedArrowDirections: .any)
.build()
.showAlert(animated: true)
}
First find out the topmost viewController on your window .
Get the top ViewController in iOS Swift
and then present your alert on that viewController.No need to pass any parameter.
public func alertUser(strTitle: String, strMessage: String) {
let myAlert = UIAlertController(title: strTitle, message: strMessage, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)
myAlert.addAction(okAction)
topmostVC().present(myAlert, animated: true, completion: nil)
}

How to make a global function for UIAlertController(ActionSheet) to access in many classes of project

I want to make a function in NSObject class for UIAlertCotroller. So that I can access this function in any class. I have tried with that following code:
open class func showActionSheet(_ delegate: UIViewController, message: String, strtittle: String, handler: ((UIAlertController) -> Void)! = nil)
{
let actionSheetController: UIAlertController = UIAlertController(title: strtittle, message: message, preferredStyle: UIAlertControllerStyle.actionSheet)
if handler == nil{
actionSheetController.addAction(UIAlertAction(title: "Default(Off)" , style: .default , handler:{ (UIAlertAction)in
}))
}
else{
actionSheetController.addAction(UIAlertAction(title: "Default(Off)" , style: .default , handler:{ (UIAlertAction)in
}))
}
delegate.present(actionSheetController, animated: true, completion: {
print("completion block")
})
}
This is the function that I made, but problem is there can be number of actions in ActionSheet and they also have different tittle and different styles.
Question: How can I make this function? Please Help.
Thanks!
Make extension of UIAlertController
extension UIAlertController{
func AlertWithTextField(_ view:UIViewController) -> UIAlertController{
let actionSheetController: UIAlertController = UIAlertController(title: "Action Sheet", message: message, preferredStyle: UIAlertControllerStyle.actionSheet)
actionSheetController.addAction(UIAlertAction(title: "No" , style: .default , handler:{ (UIAlertAction)in
}))
actionSheetController.addAction(UIAlertAction(title: "Yes" , style: .default , handler:{ (UIAlertAction)in
}))
view.present(actionSheetController, animated: true, completion: {
print("completion block")
})
return actionSheetController
}
}
Call this from your ViewController
let alert = UIAlertController()
alert.AlertWithTextField(self)
I have found solution of my problem by using this Swift - How to present ViewController when tapping button in a custom AlertController
Their are following modification that I have to do to achieve my goal. Here is the code:
In Controller Class:
Alert.showActionSheet(self, message: "Save incoming media for this chat",strtittle: "",actionTittle: ["Default(Off)","Always","Never","Cancel"],
actionStyle: [.default,.default,.default,.cancel] ,
withHandler: [defaultHandler, alwaysHandler, neverHandler, cancelHandler])
func defaultHandler(action: UIAlertAction) {
//Add code of present
print("DefaultHandler")
}
func alwaysHandler(action: UIAlertAction) {
//Add code of present
print("alwaysHandler")
}
func neverHandler(action: UIAlertAction) {
//Add code of present
print("neverHandler")
}
func cancelHandler(action: UIAlertAction) {
//Add code of present
print("cancelHandler")
}
In NSObject Class:
open class func showActionSheet(_ delegate: UIViewController, message: String, strtittle: String, actionTittle: [String], actionStyle: [UIAlertActionStyle], withHandler handler: [((UIAlertAction) -> Void)]?)
{
var actionSheetController: UIAlertController = UIAlertController()
if message != "" || strtittle != ""
{
actionSheetController = UIAlertController(title: strtittle, message: message, preferredStyle: UIAlertControllerStyle.actionSheet)
}
for i in 0..<actionTittle.count
{
actionSheetController.addAction(UIAlertAction(title: actionTittle[i],
style: actionStyle[i],
handler: handler?[i]))
}
delegate.present(actionSheetController, animated: true, completion: nil)
}
Using this I can gave number of actions, their tittle and styles to action sheet. And also I can simply call this method in each class. :)

Swift Displaying Alerts best practices

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:
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?
I ended up creating an extension for UIViewController and creating the alert function there:
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)
}
}
Swift 4
I wanted this same functionality for myself, so I made a full extension. To use it, create a new swift file in your project and name it whatever you'd like. Place the following code inside:
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)
}
}
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
}
}
As original answer from itstrueimryan at https://stackoverflow.com/a/30714429/6822183
Update for 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)
}
}
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.
The idea is to use protocol-oriented programming to create a default implementation of an alert just for 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.
And, of course, we can define parameters for the issueAlert function as well:
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.
Answer from 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,
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
}
}
}
}
Why not create a Utility function that returns the AlertView to the ViewController?
self.presentViewController(Utilities.createAlertController("errorMessage"), animated: true, completion: nil);
Updated for 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..!
I used Sigex's extension in my code, however I have added a check, if options were used or not.
If no options are given in the call, then the Alert only shows "OK" and completes with returning option 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.
I love Sigex's extension, but I spiced it up a bit to add style on button depending on the title
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)

Resources