Properly Present a UIAlertController from MSMessag

2020-04-02 07:00发布

I'm trying to figure out how to display a UIAlertController with a style of UIAlertControllerStyleActionSheet within my iMessage app extension.

The problem is, the action sheet appears below the native iMessage text field when presented when calling:

[self.view.window.rootViewController presentViewController:actionSheetController animated:YES completion:NULL];

How would I go about fixing this?

Code:

UIAlertController *actionSheetController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Clear", nil) message:nil preferredStyle:UIAlertControllerStyleActionSheet];

UIAlertAction *clear = [UIAlertAction actionWithTitle:NSLocalizedString(@"Clear", nil) style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action)
{
    [self clear];
}];

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

[actionSheetController addAction:clear];
[actionSheetController addAction:cancel];

[self.view.window.rootViewController presentViewController:actionSheetController animated:YES completion:NULL];

enter image description here

4条回答
Viruses.
2楼-- · 2020-04-02 07:14

Here is a workaround. Maybe add a little animation to make it smooth.

[self.view.window.rootViewController presentViewController:actionSheetController animated:YES completion:^{
    actionSheetController.view.frame = CGRectOffset(actionSheetController.view.frame, 0, -40);
}];
查看更多
Ridiculous、
3楼-- · 2020-04-02 07:15

Do not hardcode the y-position for the action sheet.

This could lead to ui issues on later iOS major updates, when apple changes the height of the iMessage dock. Instead use the safeAreaInsets.bottom value in order to find out by which value the view is hidden by the dock.

Here is the solution we are using:

    let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

    actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (_) in
        actionSheet.dismiss(animated: true, completion: nil)
    }))

    // Adding further actions...

    present(actionSheet, animated: true) {
        UIView.animate(withDuration: 0.2, animations: {
            actionSheet.view.frame = CGRect(x: actionSheet.view.frame.minX,
                                            y: actionSheet.view.frame.minY - self.view.safeAreaInsets.bottom,
                                            width: actionSheet.view.frame.width,
                                            height: actionSheet.view.frame.height)
        })
    }

Detail: The action sheet is hidden by the iMessage dock, because the view controllers view over which you are presenting the action sheet is tied up to the bottom of the view and not the top of the iMessage dock. This case must be considered e.g. when adding constraints to other views and its subview.


Update:

Just use the following code in order to avoid the animation above. In my case after time seeing the animation did get pretty annoying.

extension UIAlertController {
    open override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        guard let viewController = presentingViewController else { return }
        view.transform = .identity
        view.transform = .init(translationX: 0.0, y: - viewController.view.safeAreaInsets.bottom)
    }
}
查看更多
Emotional °昔
4楼-- · 2020-04-02 07:24

Another workaround:

actionSheetController.view.transform = CGAffineTransform(translationX: 0, y: -40)    
[self.view.window.rootViewController presentViewController:actionSheetController animated:YES completion:NULL];
查看更多
倾城 Initia
5楼-- · 2020-04-02 07:30

according to this, you can request full screen presentation by:

[self requestPresentationStyle:MSMessagesAppPresentationStyleExpanded];

before your code:

[self.view.window.rootViewController presentViewController:actionSheetController animated:YES completion:NULL];
查看更多
登录 后发表回答