How to use UIAlertController to replace UIActionSheet?

前端 未结 6 1366
醉话见心
醉话见心 2020-12-13 23:29

I am maintaining an old iOS project which based on SDK 6.0.

A method on this project called

-(void) showComboBox:(UIView*)view:withOptions:(NSDictiona

相关标签:
6条回答
  • 2020-12-13 23:49

    I have used action sheet for changing profile picture. I followed Kampai approach, just removed dismissviewController call since it was kicking me out of a view when pressing Cancel or photo selection view

    UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
    
    [actionSheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
    
        // Cancel button tappped do nothing.
    
    }]];
    
    [actionSheet addAction:[UIAlertAction actionWithTitle:@"Take photo" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
    
        // take photo button tapped.
        [self takePhoto];
    
    }]];
    
    [actionSheet addAction:[UIAlertAction actionWithTitle:@"Choose photo" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
    
        // choose photo button tapped.
        [self choosePhoto];
    
    }]];
    
    [actionSheet addAction:[UIAlertAction actionWithTitle:@"Delete Photo" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {
    
        // Distructive button tapped.
        [self deletePhoto];
    
    }]];
    
    0 讨论(0)
  • 2020-12-13 23:56

    Swift 4

            let alert = UIAlertController(title: "Select One", message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)
            alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil))
            alert.addAction(UIAlertAction(title: "Export", style: UIAlertActionStyle.default, handler: { (action) in
    
                // TODO: Export wordlist
    
            }))
            alert.addAction(UIAlertAction(title: "Import", style: UIAlertActionStyle.default, handler: { (action) in
    
                // TODO: Import wordlist
            }))
    
            self.present(alert, animated: true, completion: nil)
    
    0 讨论(0)
  • 2020-12-13 23:57

    You can use view.window.rootViewController instead. If you don't care about presenter it is fine.

    0 讨论(0)
  • 2020-12-14 00:05

    Swift update -

        let actionSheet = UIAlertController.init(title: "Please choose a source type", message: nil, preferredStyle: .actionSheet)
        actionSheet.addAction(UIAlertAction.init(title: "Take Photo", style: UIAlertActionStyle.default, handler: { (action) in
            self.openCamera()
        }))
        actionSheet.addAction(UIAlertAction.init(title: "Choose Photo", style: UIAlertActionStyle.default, handler: { (action) in
            self.showPhotoLibrary()
        }))
        actionSheet.addAction(UIAlertAction.init(title: "Cancel", style: UIAlertActionStyle.cancel, handler: { (action) in
            // self.dismissViewControllerAnimated(true, completion: nil) is not needed, this is handled automatically,
             //Plus whatever method you define here, gets called,
            //If you tap outside the UIAlertController action buttons area, then also this handler gets called.
        }))
        //Present the controller
        self.present(actionSheet, animated: true, completion: nil)
    
    0 讨论(0)
  • 2020-12-14 00:10

    While it may look very simple, there is a nasty issue with using UIAlertController. It is memory leaks prone. In order to test if you have the issue, just put a breakpoint at your view controller's dealloc method and see if it's deallocated properly.

    I was looking for a solution for quite some time and here is how I use an alert controller in my app.

    + (void)alertWithPresenting:(UIViewController *)presenting title:(NSString *)title
                           text:(NSString *)text buttons:(NSArray *)buttons
                        handler:(void (^)(UIAlertAction *action, NSUInteger index))handler
    {
            UIAlertController *alert = [UIAlertController
                                        alertControllerWithTitle:title message:text
                                        preferredStyle:UIAlertControllerStyleAlert];
            __weak __typeof(alert) weakAlert = alert;
            for (NSString *title in buttons) {
                    UIAlertActionStyle style = UIAlertActionStyleDefault;
                    if ([title isEqualToString:[L10n cancelButton]])
                            style = UIAlertActionStyleCancel;
                    else if ([title isEqualToString:[L10n deleteButton]])
                            style = UIAlertActionStyleDestructive;
                    else if ([title isEqualToString:[L10n archiveButton]])
                            style = UIAlertActionStyleDestructive;
    
                    UIAlertAction *action = [UIAlertAction actionWithTitle:title style:style handler:^(UIAlertAction *action) {
                            if (handler != nil)
                                    handler(action, [buttons indexOfObject:action.title]);
                            [weakAlert dismissViewControllerAnimated:YES completion:nil];
                    }];
                    [alert addAction:action];
            }
            [presenting presentViewController:alert animated:YES completion:nil];
    }
    

    This is not all. Here is an example of how you use it in your view controller. In my case its tableview with search, so presenting controller may be different.

    - (void) deleteCases:(NSArray *)selectedRows
    {
            NSString *text = NSLocalizedStringWithDefaultValue(@"cases.delete.alert.text",
                                                               @"Localizable",  [NSBundle mainBundle],
                                                               @"Deleted cases cannot be restored. Continue with delete?",
                                                               @"Delete alert text");
            NSString *title = NSLocalizedStringWithDefaultValue(@"cases.delete.alert.title",
                                                                @"Localizable",  [NSBundle mainBundle],
                                                                @"Delete cases", @"Detete alert title");
            UIViewController *presenting = self.searchController.active ? self.searchController : self;
            __weak __typeof(presenting) weakPresenting = presenting;
            __weak __typeof(self) weakSelf = self;
            [YourClassName alertWithPresenting:weakPresenting title:title text:text
                                       buttons:@[[L10n deleteButton], [L10n cancelButton]]
                                       handler:^(UIAlertAction *action, NSUInteger index)
            {
                    if (action.style == UIAlertActionStyleDestructive) {
                            __typeof(weakSelf) strongSelf = weakSelf;
                            // Perform your actions using @strongSelf
                    }
             }];
    }
    
    0 讨论(0)
  • 2020-12-14 00:12

    I have used following code to show action sheet using UIAlertViewController and it works perfect.

    Swift

    let alert = UIAlertController(title: "Action Title", message: "Action Message", preferredStyle: .actionSheet)
    let action = UIAlertAction(title: "Item", style: .default) {
        UIAlertAction in
        // Write your code here
    }
    alert.addAction(action)
    
    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) {
        UIAlertAction in
        // It will dismiss action sheet
    }
    alert.addAction(cancelAction)
    self.present(alert, animated: true, completion: nil)
    

    Objective C

    - (IBAction)buttonClicked:(id)sender {
    
        UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:@"Action Sheet" message:@"Using the alert controller" preferredStyle:UIAlertControllerStyleActionSheet];
    
        [actionSheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
    
            // Cancel button tappped.
            [self dismissViewControllerAnimated:YES completion:^{
            }];
        }]];
    
        [actionSheet addAction:[UIAlertAction actionWithTitle:@"Delete" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {
    
            // Distructive button tapped.
            [self dismissViewControllerAnimated:YES completion:^{
            }];
        }]];
    
        [actionSheet addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
    
            // OK button tapped.
    
            [self dismissViewControllerAnimated:YES completion:^{
            }];
        }]];
    
        // Present action sheet.
        [self presentViewController:actionSheet animated:YES completion:nil];
    }
    

    Edit:

    You need to get UIViewController object here. You can set global variable or call a delegate method, or you can use notification to get view controller object in this code.

    and last line in above code will be like.

    [self.viewController presentViewController:actionSheet animated:YES completion:nil];
    

    self.viewController is a global variable which will be set before you actually get this view.

    Because the approach you are following now using view.nextResponder. I'm afraid that it may not work.

    0 讨论(0)
提交回复
热议问题