Pyae Phyoe Shein
Pyae Phyoe Shein

Reputation: 13787

How to create uialertcontroller in global swift

I'm trying to create uialertcontroller in Config.swift file as follow.

static func showAlertMessage(titleStr:String, messageStr:String) -> Void {
    let window : UIWindow?
    let alert = UIAlertController(title: titleStr, message: messageStr, preferredStyle: UIAlertControllerStyle.Alert);
    self.window!.presentViewController(alert, animated: true, completion: nil)
}

problem is I've found problem in self.window!.

Type 'Config' has no member 'window'

Please let me know how to solve that issue.

Upvotes: 12

Views: 19357

Answers (12)

Yogesh Patel
Yogesh Patel

Reputation: 2017

Details

  • Swift 5.1, Xcode 11.3.1

Global UIAlertController With UIViewController Extension

extension UIViewController{

    // Global Alert
    // Define Your number of buttons, styles and completion
    public func openAlert(title: String,
                          message: String,
                          alertStyle:UIAlertController.Style,
                          actionTitles:[String],
                          actionStyles:[UIAlertAction.Style],
                          actions: [((UIAlertAction) -> Void)]){

        let alertController = UIAlertController(title: title, message: message, preferredStyle: alertStyle)
        for(index, indexTitle) in actionTitles.enumerated(){
            let action = UIAlertAction(title: indexTitle, style: actionStyles[index], handler: actions[index])
            alertController.addAction(action)
        }
        self.present(alertController, animated: true)
    }
}

Usage

Alert

self.openAlert(title: "alert",
                      message: "add your message",
                      alertStyle: .alert,
                      actionTitles: ["Okay", "Cancel"],
                      actionStyles: [.default, .cancel],
                      actions: [
                          {_ in
                               print("okay click")
                          },
                          {_ in
                               print("cancel click")
                          }
                     ])

ActionSheet

self.openAlert(title: "actionsheet",
                  message: "add your message",
                  alertStyle: .actionSheet,
                  actionTitles: ["Okay", "Cancel"],
                  actionStyles: [.default, .cancel],
                  actions: [
                      {_ in
                           print("okay click")
                      },
                      {_ in
                           print("cancel click")
                      }
                 ])

Upvotes: 9

Mehul Chuahan
Mehul Chuahan

Reputation: 752

This is also the way you can present on top of the View Controller available.

UIApplication.topViewController()?.present(alertViewController!, animated: true, completion: nil)

Upvotes: 0

William Hu
William Hu

Reputation: 16141

swift

Here's what I used, this is the same as @penatheboss answered, just add the ability of adding actions and handlers.

extension UIViewController {
    func popupAlert(title: String?, message: String?, actionTitles:[String?], actions:[((UIAlertAction) -> Void)?]) {
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        for (index, title) in actionTitles.enumerated() {
            let action = UIAlertAction(title: title, style: .default, handler: actions[index])
            alert.addAction(action)
        }
        self.present(alert, animated: true, completion: nil)
    }
}

Just make sure actionTitles and actions array the same count. Pass nil if you don't need any action handler closure.

self.popupAlert(title: "Title", message: " Oops, xxxx ", actionTitles: ["Option1","Option2","Option3"], actions:[{action1 in

},{action2 in

}, nil])

Objective C:

Add the category for UIViewController

UIViewController+PopAlert.h

#import <UIKit/UIKit.h>

@interface UIViewController (UIViewControllerCategory)
- (void) popAlertWithTitle: (NSString*) title message: (NSString*) message actionTitles:(NSArray *) actionTitles actions:(NSArray*)actions;
@end

UIViewController+PopAlert.m

#import "UIViewController+PopAlert.h"

@implementation UIViewController (UIViewControllerCategory)
- (void) popAlertWithTitle: (NSString*) title message: (NSString*) message actionTitles:(NSArray *) actionTitles actions:(NSArray*)actions {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
    [actionTitles enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        UIAlertAction *action = [UIAlertAction actionWithTitle:obj style:UIAlertActionStyleDefault handler:actions[idx]];
        [alert addAction:action];
    }];
    [self presentViewController:alert animated:YES completion:nil];
}
@end

Usage:

#import UIViewController+PopAlert.h

...

[super viewDidDisappear:animated];
    NSArray *actions = @[^(){NSLog(@"I am action1");}, ^(){NSLog(@"I am action2");}];
    [self popAlertWithTitle:@"I am title" message:@"good" actionTitles:@[@"good1", @"good2"] actions:actions];

Upvotes: 37

Sandip Patel - SM
Sandip Patel - SM

Reputation: 3394

You can use my Utility class created for Show Alert in Swift4. Its super easy to use just by writing single line of code:

Show Simple Alert

@IBAction func showDefaultAlert(_ sender: Any) {

  Alert.showAlert(title:"Alert", message:"Default Alert")

}

Demo code link: https://github.com/smindia1988/EasyAlertInSwift4

Upvotes: 1

Sunil aruru
Sunil aruru

Reputation: 497

You can try this, please add below code in AppDelegate.swift file.

 static func showAlertView(vc : UIViewController, titleString : String , messageString: String) ->()
    {
        let alertView = UIAlertController(title: titleString, message: messageString, preferredStyle: .alert)

        let alertAction = UIAlertAction(title: "ok", style: .cancel) { (alert) in
            vc.dismiss(animated: true, completion: nil)
        }
        alertView.addAction(alertAction)
        vc.present(alertView, animated: true, completion: nil)

    }

and call showAlertView method from any viewcontroller

AppDelegate.showAlertView(vc: self, titleString: "testTitle", messageString: "test msg")

Upvotes: 2

Kanchu
Kanchu

Reputation: 3809

What I'm using based on the solution by @William Hu:

func popup(caller:UIViewController, style:UIAlertControllerStyle? = UIAlertControllerStyle.alert,
        title:String, message:String, buttonTexts:[String], buttonStyles:([UIAlertActionStyle?])? = nil,
        handlers:[((UIAlertAction) -> Void)?], animated:Bool? = nil, completion: (() -> Void)? = nil) {
    let alert = UIAlertController(title: title, message: message, preferredStyle: style!)
    for i in 0..<buttonTexts.count {
        alert.addAction(UIAlertAction(title: buttonTexts[i],
            style: (buttonStyles == nil || i >= buttonStyles!.count || buttonStyles![i] == nil ?
                UIAlertActionStyle.default : buttonStyles![i]!),
            handler: (i >= handlers.count || handlers[i] == nil ? nil : handlers[i]!)))
    }
    caller.present(alert, animated: animated != nil ? animated! : true, completion: completion)
}
  1. Single function gives Alert by default and can optionally be used for ActionSheet.
  2. Arrays buttonTexts, buttonStyles and handlers can be of unequal sizes as per requirement.
  3. Actions can be styled.
  4. Animated can be specified.
  5. Optional block can be specified to be executed when presentation finishes.

Usage:

popup(caller: self, style: UIAlertControllerStyle.alert,
        title: "Title", message: "Message",
        buttonTexts: ["Destructive", "Cancel", "OK"],
        buttonStyles: [UIAlertActionStyle.destructive, UIAlertActionStyle.cancel],
        handlers: [nil], animated: false)

Upvotes: 1

Amila Munasinghe
Amila Munasinghe

Reputation: 13

Please refer the below GIT Example

https://github.com/amilaim/CommonAlertView

//  ViewController.swift
//  CommonAlertView
//
//  Created by Amila Munasinghe on 4/25/17.
//  Copyright © 2017 Developer Insight. All rights reserved.
//
import UIKit

class ViewController: UIViewController,AlertViewControllerDelegate {

@IBOutlet weak var AlertViewResultTextOutlet: UITextField!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}

@IBAction func ShowAlertAction(_ sender: Any) {

    let alert = AlertViewController.sharedInstance
    alert.delegate = self
    alert.SubmitAlertView(viewController: self,title: "Developer Insight", message: "Please enter any text value")

}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


func SubmitAlertViewResult(textValue : String) {

    AlertViewResultTextOutlet.text = textValue

 } 
}

Common UIAlertViewController Implementation

import UIKit

protocol AlertViewControllerDelegate {
func SubmitAlertViewResult(textValue : String)
 }

class AlertViewController {

static let sharedInstance = AlertViewController()

private init(){}

var delegate : AlertViewControllerDelegate?

func SubmitAlertView(viewController : UIViewController,title : String, message : String){

    let alert = UIAlertController(title: title,
                                  message: message,
                                  preferredStyle: .alert)

    // Submit button
    let submitAction = UIAlertAction(title: "Submit", style: .default, handler: { (action) -> Void in
        // Get 1st TextField's text
        let textField = alert.textFields![0]

        if(textField.text != "")
        {
            self.delegate?.SubmitAlertViewResult(textValue: textField.text!)
        }

    })

    // Cancel button
    let cancel = UIAlertAction(title: "Cancel", style: .destructive, handler: { (action) -> Void in })


    // Add 1 textField and cutomize it
    alert.addTextField { (textField: UITextField) in
        textField.keyboardAppearance = .dark
        textField.keyboardType = .default
        textField.autocorrectionType = .default
        textField.placeholder = "enter any text value"
        textField.clearButtonMode = .whileEditing

    }

    // Add action buttons and present the Alert
    alert.addAction(submitAction)
    alert.addAction(cancel)
    viewController.present(alert, animated: true, completion: nil)

 }

}

Upvotes: 1

Subin K Kuriakose
Subin K Kuriakose

Reputation: 849

I created a alerMessage class .I can call any where in my application

//Common Alert Message Class 

class AlertMessage {

internal static var alertMessageController:UIAlertController!

internal static func disPlayAlertMessage(titleMessage:String, alertMsg:String){


    AlertMessage.alertMessageController = UIAlertController(title: titleMessage, message:
        alertMsg, preferredStyle: UIAlertControllerStyle.Alert)

    AlertMessage.alertMessageController.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default,handler: nil))
    if let controller = UIApplication.sharedApplication().keyWindow?.rootViewController?.presentedViewController {
        controller.presentViewController(AlertMessage.alertMessageController, animated: true, completion: nil)
    }
    else{
        UIApplication.sharedApplication().delegate?.window!!.rootViewController?.presentViewController(AlertMessage.alertMessageController, animated: true, completion: nil)
    }

    return

 }
}

Upvotes: 1

Pranav Wadhwa
Pranav Wadhwa

Reputation: 7736

I suggest creating an extension:

extension UIViewController {
    func showAlertMessage(titleStr:String, messageStr:String) {
        let alert = UIAlertController(title: titleStr, message: messageStr, preferredStyle: UIAlertControllerStyle.Alert)
       self.presentViewController(alert, animated: true, completion: nil)
    }
}

Upvotes: 2

Rahul
Rahul

Reputation: 357

If you want to present from AppDelegate windows you can use like this

UIApplication.sharedApplication().delegate?.window.rootViewController?.presentViewController(vc, animated: true, completion: nil)

Upvotes: 0

Eric Aya
Eric Aya

Reputation: 70096

self.window would mean that there's a window object in this class, and it's not the case.

You would need to use your let window : UIWindow? with window?.presentViewController(alert, animated: true, completion: nil), but this won't help, since this window does not actually represent any existing window, and it's not a view controller anyway.

So I suggest you pass the actual view controller you'll be using to the method:

static func showAlertMessage(vc: UIViewController, titleStr:String, messageStr:String) -> Void {
    let alert = UIAlertController(title: titleStr, message: messageStr, preferredStyle: UIAlertControllerStyle.Alert);
    vc.presentViewController(alert, animated: true, completion: nil)
}

and you call it from a class where a UIViewController object is available.

Upvotes: 17

maquannene
maquannene

Reputation: 2307

I am suggest you write this code, but if you really need, try this:

static func showAlertMessage(titleStr:String, messageStr:String) -> Void {
    let alert = UIAlertController(title: titleStr, message: messageStr, preferredStyle: UIAlertControllerStyle.Alert);
    if let viewController = UIApplication.sharedApplication().windows.first?.rootViewController as UIViewController? {
        viewController.presentViewController(alert, animated: true, completion: nil)
    }
}

At least it won't break down.

@Eric D better answer.

Upvotes: 1

Related Questions