Skip to content

Commit

Permalink
[Dialogs] Adds dismissOnAction property to MDCAlertAction to allow ca…
Browse files Browse the repository at this point in the history
…llers to control when the dialog dismisses.

PiperOrigin-RevId: 358818579
  • Loading branch information
Nobody authored and material-automation committed Feb 22, 2021
1 parent 2416f19 commit 9c91e26
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 16 deletions.
27 changes: 25 additions & 2 deletions components/Dialogs/src/MDCAlertController.h
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,8 @@ typedef void (^MDCActionHandler)(MDCAlertAction *_Nonnull action);
bottom of an alert controller.
@param title The title of the button shown on the alert dialog.
@param handler A block to execute when the user selects the action.
@param handler A block to execute when the user selects the action. This is called any
time the action is selected, even if @c dismissOnAction is @c NO.
@return An initialized @c MDCActionAlert object.
*/
+ (nonnull instancetype)actionWithTitle:(nonnull NSString *)title
Expand All @@ -457,7 +458,8 @@ typedef void (^MDCActionHandler)(MDCAlertAction *_Nonnull action);
@param emphasis The emphasis of the button that will be rendered in the alert dialog.
Unthemed actions will render all emphases as text. Apply themers to the alert
to achieve different appearance for different emphases.
@param handler A block to execute when the user selects the action.
@param handler A block to execute when the user selects the action. This is called any
time the action is selected, even if @c dismissOnAction is @c NO.
@return An initialized @c MDCActionAlert object.
*/
+ (nonnull instancetype)actionWithTitle:(nonnull NSString *)title
Expand All @@ -484,4 +486,25 @@ typedef void (^MDCActionHandler)(MDCAlertAction *_Nonnull action);
*/
@property(nonatomic, nullable, copy) NSString *accessibilityIdentifier;

/**
Whether actions dismiss the dialog on action selection or persist the dialog after a selection has
been made. If this is set to @c NO, then it is up to the presenting class to dismiss the
controller. Callers may dismiss the controller by calling dismissViewControllerAnimated:completion:
on the presenting view controller. Ex:
__weak MDCAlertController *weakAlertController = alertController;
MDCAlertAction *action = [MDCAlertAction actionWithTitle:@"Title" handler:^{
MDCAlertController *strongAlertController = weakAlertController;
if (strongAlertController) {
[strongAlertController.presentingViewController dismissViewControllerAnimated:YES
completion:nil];
}
}];
action.dismissOnAction = NO;
[alertController addAction:action];
Defaults to @c YES meaning that when an action is performed, it also dismisses the dialog.
*/
@property(nonatomic, assign) BOOL dismissOnAction;

@end
32 changes: 19 additions & 13 deletions components/Dialogs/src/MDCAlertController.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

@interface MDCAlertAction ()

@property(nonatomic, nullable, copy) MDCActionHandler completionHandler;
@property(nonatomic, nullable, copy) MDCActionHandler tapHandler;

@end

Expand All @@ -51,8 +51,9 @@ - (instancetype)initWithTitle:(nonnull NSString *)title
self = [super init];
if (self) {
_title = [title copy];
_dismissOnAction = YES;
_emphasis = emphasis;
_completionHandler = [handler copy];
_tapHandler = [handler copy];
}
return self;
}
Expand All @@ -62,7 +63,7 @@ - (instancetype)initWithTitle:(nonnull NSString *)title
- (id)copyWithZone:(__unused NSZone *)zone {
MDCAlertAction *action = [[self class] actionWithTitle:self.title
emphasis:self.emphasis
handler:self.completionHandler];
handler:self.tapHandler];
action.accessibilityIdentifier = self.accessibilityIdentifier;

return action;
Expand Down Expand Up @@ -594,16 +595,21 @@ - (void)actionButtonPressed:(id)button forEvent:(UIEvent *)event {
[self.delegate alertController:self didTapAction:action withEvent:event];
}

// We call our action.completionHandler after we dismiss the existing alert in case the handler
// also presents a view controller. Otherwise we get a warning about presenting on a controller
// which is already presenting.
[self.presentingViewController
dismissViewControllerAnimated:YES
completion:^(void) {
if (action.completionHandler) {
action.completionHandler(action);
}
}];
if (action.dismissOnAction) {
// We call our action.tapHandler after we dismiss the existing alert in case the handler
// also presents a view controller. Otherwise we get a warning about presenting on a controller
// which is already presenting.
[self.presentingViewController dismissViewControllerAnimated:YES
completion:^(void) {
if (action.tapHandler) {
action.tapHandler(action);
}
}];
} else {
if (action.tapHandler) {
action.tapHandler(action);
}
}
}

#pragma mark - Text View Delegate
Expand Down
3 changes: 2 additions & 1 deletion components/Dialogs/src/MDCAlertControllerDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@

/**
Called on the delegate after the alert action is tapped by the user and while the alert is still on
the screen.
the screen. This is called whenever the action is tapped regardless of whether it dismisses the
alert controller or not.
*/
- (void)alertController:(nonnull MDCAlertController *)alertController
didTapAction:(nonnull MDCAlertAction *)action
Expand Down

0 comments on commit 9c91e26

Please sign in to comment.