BlackHatSamurai
BlackHatSamurai

Reputation: 23483

UIAlertController Not Working with Swift 3.0

I have the following alert method.

static func notifyUser(_ title: String, message: String) -> Void
{
    let alert = UIAlertController(title: title,
                                  message: message,
                                  preferredStyle: UIAlertControllerStyle.alert)

    let cancelAction = UIAlertAction(title: "OK",
                                     style: .cancel, handler: nil)

    alert.addAction(cancelAction)
    self.presentViewController(alert, animated: true, completion: nil)
}

I get an error saying that there is an extra argument animated in the presentViewController method, but when I take it out, it still doesn't dismiss the error, and then I'm told that completion is an extra argument.

Upvotes: 18

Views: 31909

Answers (6)

Anju Sathish
Anju Sathish

Reputation: 1

let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
if action {
    alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: {
        (action : UIAlertAction!) in self.navigationController?.popViewController(animated: true)
    }))
} else {
    alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
}
self.present(alert, animated: true, completion: nil)

Upvotes: 0

Syed Qamar Abbas
Syed Qamar Abbas

Reputation: 3677

You are trying to use self in a static method while self should be the current instance of that class but static cannot use self.

Without Action Handler For Alert Button

In Obj-C

+(void) notifyUser:(NSString *)title withMessage:(NSString *)message onViewController:(UIViewController *)vc {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil];
    [alert addAction:action];
    //vc will be the view controller on which you will present your alert as you cannot use self because this method is static.
    [vc presentViewController:alert animated:true completion:nil];
}

In Swift 3.0

static func notifyUser(_ title: String, message: String, vc: UIViewController) -> Void
    {
        let alert = UIAlertController(title: title,
                                      message: message,
                                      preferredStyle: UIAlertControllerStyle.alert)

        let cancelAction = UIAlertAction(title: "OK",
                                         style: .cancel, handler: nil)

        alert.addAction(cancelAction)
        //vc will be the view controller on which you will present your alert as you cannot use self because this method is static.
        vc.present(alert, animated: true, completion: nil)
    }

With Action Handler For Alert Button

In Obj-C

+(void) notifyUser:(NSString *)title withMessage:(NSString *)message withButtonTitles:(NSArray<NSString *> *)buttonTitles andButtonStyles:(NSArray *)styles onViewController:(UIViewController *)vc onCompletion:(void (^)(NSInteger))completion  {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];

    for (NSString *title in buttonTitles) {
        UIAlertActionStyle style = [[styles objectAtIndex:[buttonTitles indexOfObject:title]] intValue];

        UIAlertAction *actionObj = [UIAlertAction actionWithTitle:title style:style handler:^(UIAlertAction *action){
            NSInteger index = [buttonTitles indexOfObject:action.title];
            completion(index);
        }];
        [alert addAction:actionObj];
    }
    //vc will be the view controller on which you will present your alert as you cannot use self because this method is static.
    [vc presentViewController:alert animated:true completion:nil];
}

Invoke above instance method like this.

[ClassName notifyUser:@"Title For Alert" withMessage:@"Message for Alert" withButtonTitles:@[@"Camera",@"Library",@"Dismiss"] andButtonStyles:@[@(UIAlertActionStyleDefault),@(UIAlertActionStyleDefault),@(UIAlertActionStyleCancel)] onViewController:yourViewController onCompletion:^(NSInteger indexOfTappedButton){
                    //Note the index of the button will have the same order as you have provide the titles array in this method
    }];

Here yourViewController is the controller on which you will present this Alert

In Swift 3.0

extension UIAlertController {
    static func notifyUser(_ title: String, message: String, alertButtonTitles: [String], alertButtonStyles: [UIAlertActionStyle], vc: UIViewController, completion: @escaping (Int)->Void) -> Void
    {
        let alert = UIAlertController(title: title,
                                      message: message,
                                      preferredStyle: UIAlertControllerStyle.alert)

        for title in alertButtonTitles {
            let actionObj = UIAlertAction(title: title,
                                          style: alertButtonStyles[alertButtonTitles.index(of: title)!], handler: { action in
                                            completion(alertButtonTitles.index(of: action.title!)!)
            })

            alert.addAction(actionObj)
        }


        //vc will be the view controller on which you will present your alert as you cannot use self because this method is static.
        vc.present(alert, animated: true, completion: nil)
    }
}

Invoke above static method like this.

UIAlertController.notifyUser("Title for Alert", message: "Message show in Alert", alertButtonTitles: ["Camera", "Library","Dismiss"], alertButtonStyles: [.default,.default,.cancel], vc: yourViewController, completion: { indexOfTappedButton in
            //Note the index of the button will have the same order as you have provide the titles array in this method
        })

Here yourViewController is the controller on which you will present this Alert

Upvotes: 4

Nirav D
Nirav D

Reputation: 72410

presentViewController is changed in Swift 3 like this.

present(alert, animated: true)

Check Apple Documentation for more details.

From Swift 3 completionis optional so if you doesn't want handle the completion block no need to write nil for that and if you want to handle completion block then write like this.

self.present(alert, animated: true) { 

}

Note: Your notifyUser method is declared with static so you cannot use self with it so remove that also to remove the next error that you get after correcting this one.

Upvotes: 27

amiron
amiron

Reputation: 731

Swift 3 Try Custom Action Cancel

  let uiAlertController = UIAlertController(// create new instance alert  controller
          title: "You TITLE text",
          message: "You Message text", 
          preferredStyle:.alert)

    uiAlertController.addAction(// add Custom action on Event is Cancel
    UIAlertAction.init(title: "Cancel", style: .default, handler: { (UIAlertAction) in
       //TO DO code
       uiAlertController.dismiss(animated: true, completion: nil)//dismiss show You alert, on click is Cancel
    }))
    //show You alert
    self.present(uiAlertController, animated: true, completion: nil)

Upvotes: 2

Giang
Giang

Reputation: 3645

Swift 3

let alertView = UIAlertController(title: "", message: "your message", preferredStyle: .alert)
let action = UIAlertAction(title: "OK", style: .default, handler: { (alert) in

})
alertView.addAction(action)
self.present(alertView, animated: true, completion: nil)

Upvotes: 11

Himanshu Moradiya
Himanshu Moradiya

Reputation: 4815

 let actionSheetController: UIAlertController = UIAlertController(title: "Action Sheet", message: "Swiftly Now! Choose an option!", preferredStyle: .alert)
 let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .cancel) { action -> Void in
            //Just dismiss the action sheet
        }
 actionSheetController.addAction(cancelAction)
 self.present(actionSheetController, animated: true, completion: nil)

Upvotes: 27

Related Questions