본문 바로가기
모바일개발(Mobile Dev)/IOS개발(ObjectC)

How to use UIAlertController

by 테크한스 2015. 12. 27.
반응형


written by http://recursivesteps.net/blog/2014/12/17/uialertcontroller/


UIAlertController

As a programmer, I really like the idea of UIAlertView and UIActionSheet. This is simply because they don’t mess with the view hierachy. So whenever I have an app that’s not conforming to the view life-cycle, I tend to use these instead of views on their own.
Sadly they are limited. By default you can’t have more than two textfields added in an UIAlertView. Of course you could hack them in there, as is suggested on Stack Overflow multiple times, but you never know if Apple won’t reject your app because you messed with their view hierachy.

I really liked this version, but I don’t want to test Apples submission process if I don’t have to:

UIAlertViewlink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
-(IBAction) showAlertView {

    UIAlertView *alert;
    UITextField *callForwardNumber;
    UItextField *callForwardCondition;

    alert = [[UIAlertView alloc] initWithTitle:@"Enter Phone Number & Rule"
                                   message:@""
                                  delegate:self
                         cancelButtonTitle:@"Cancel"
                         otherButtonTitles:@"Save", nil];

    //alert.transform = CGAffineTransformMakeTranslation(0, 110);

    callForwardNumber = [[UITextField alloc] init];
    callForwardNumber.keyboardType = UIKeyboardTypeNumberPad;
    callForwardNumber.text = [R.prefs objectForKey:@"gtalkpbx_fwd_number"];
    callForwardNumber.borderStyle = UITextBorderStyleRoundedRect;
    callForwardNumber.delegate = self;
    callForwardNumber.tag = 1;

    callForwardCondition = [[UITextField alloc] init];
    callForwardCondition.text = callCondition;
    callForwardCondition.borderStyle = UITextBorderStyleRoundedRect;
    callForwardCondition.delegate = self;
    callForwardCondition.tag = 2;
    [callForwardCondition setKeyboardType:UIKeyboardTypeNumberPad];

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
    UIView* customAccessory =
                   [[UIView alloc] initWithFrame:CGRectMake(0, 0, 250, 55)];
    callForwardNumber.frame = CGRectMake(0, 0, 245.0, 25.0);
    callForwardCondition.frame = CGRectMake(0, 30.0, 245.0, 25.0);
    [customAccessory addSubview:callForwardNumber];
    [customAccessory addSubview:callForwardCondition];
    [alert setValue:customAccessory forKey:@"accessoryView"];
    [alert show];
} else {
    alert.message = @"\n\n\n";
    [alert show];
    callForwardNumber.frame = CGRectMake(20.0, 45.0, 245.0, 25.0);
    callForwardCondition.frame = CGRectMake(20.0, 75.0, 245.0, 25.0);
    [alert addSubview:callForwardNumber];
    [alert addSubview:callForwardCondition];
}

}

But with iOS 8 Apple was merciful and replaced both with the UIAlertController. Thus UIAlertView and UIActionSheet are deprecated, even though XCode doesn’t alert you about it. And you still need it, if you want to support iOS 7.

So without further ado, here is what you do from now on…

UIAlertView vs UIAlertController

UIAlertView
1
2
3
4
5
6
7
8
9
10
11
- (IBAction)showAlertView:(id)sender {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"AlertView" message:@"shown by UIAlertView" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK",nil];

    [alert show];
}

// Delegate

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {

}
UIAlertController
1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (IBAction)showAlertController:(id)sender {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"AlertView" message:@"shown by UIAlertController" preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction *doCancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
    }];

    UIAlertAction *doOKAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
    }];

    [alert addAction:doCancelAction];
    [alert addAction:doOKAction];

    [self presentViewController:alert animated:YES completion:nil];
}

So what is the difference? First of all, we don’t need delegates anymore. Depending on your preference, this is a good or a bad thing. Instead, we write every action as a block.
The second interesting thing is that we can just add as many Actions and Textfields as we want. UIAlertController is not defined by its limited options, as UIAlertView was.

Add Textfield to AlertController
1
2
3
4
[alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
        textField.placeholder = @"Placeholder";
        textField.keyboardType = UIKeyboardTypeDefault;
    }];

To access the added textfields use the textFields property of the UIAlertController.

UIActionSheet vs UIAlertController

UIActionSheet
1
2
3
4
5
6
7
8
9
10
- (IBAction)showActionSheet:(id)sender {
    UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"ActionSheet" delegate:nil cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Destructive" otherButtonTitles:@"UIActionSheet", nil];
    [sheet showInView:self.view];
}

// Delegate

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {

}
UIAlertController
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (IBAction)showActionController:(id)sender {
    UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:@"ActionSheet" message:@"" preferredStyle:UIAlertControllerStyleActionSheet];

    UIAlertAction *destructiveAction = [UIAlertAction actionWithTitle:@"Destructive" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {
    }];

    UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
    }];

    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"UIAlertController" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
    }];

    [actionSheet addAction:destructiveAction];
    [actionSheet addAction:defaultAction];
    [actionSheet addAction:cancelAction];

    [self presentViewController:actionSheet animated:YES completion:nil];
}

As you can see, there is not such a huge difference to creating an Alert. Once again, we use blocks instead of delegates and define the type of action when we create an action.

Summary

UIAlertController replaces the deprecated classes UIAlertView and UIActionSheet. It also replaces delegates with blocks (Objective-C) / closures (Swift), thus getting rid of this if (buttonTitle == @"ButtonTitle") tests.
The steps to create an UIAlertController are these:
1. Create an instance of UIAlertController and set its preferredStyle: 2. Add actions in blocks/closures 3. If necessary add textfields 4. Present

P.S. Be careful. Adding a textfield to an ActionSheet results in an exception.


반응형