Правильно представить UIAlertController от MSMessagesAppViewController

Я пытаюсь выяснить, как отобразить UIAlertController со стилем UIAlertControllerStyleActionSheet в моем расширении приложения iMessage.

Проблема в том, что лист действий появляется под собственным текстовым полем iMessage, когда отображается при вызове:

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

Как мне исправить это?

Код:

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];

4 ответа

Вот обходной путь. Может быть, добавить немного анимации, чтобы сделать его гладким.

[self.view.window.rootViewController presentViewController:actionSheetController animated:YES completion:^{
    actionSheetController.view.frame = CGRectOffset(actionSheetController.view.frame, 0, -40);
}];

Другой обходной путь:

actionSheetController.view.transform = CGAffineTransform(translationX: 0, y: -40)    
[self.view.window.rootViewController presentViewController:actionSheetController animated:YES completion:NULL];

Не жестко кодируйте y-позицию для листа действий.

Это может привести к проблемам с пользовательским интерфейсом в более поздних основных обновлениях iOS, когда яблоко меняет высоту дока iMessage. Вместо этого используйте safeAreaInsets.bottom значение, чтобы узнать, по какому значению вид скрывается доком.

Вот решение, которое мы используем:

    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)
        })
    }

Подробно: лист действий скрыт док-станцией iMessage, потому что представление контроллеров представления, над которым вы представляете лист действий, привязано к нижней части вида, а не к верхней части док-станции iMessage. Этот случай должен быть рассмотрен, например, при добавлении ограничений к другим представлениям и их подпредставлениям.


Обновить:

Просто используйте следующий код, чтобы избежать анимации выше. В моем случае, после того, как я увидел время, анимация стала довольно раздражающей.

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)
    }
}

В соответствии с этим вы можете запросить полноэкранное представление по:

[self requestPresentationStyle:MSMessagesAppPresentationStyleExpanded];

перед вашим кодом:

[self.view.window.rootViewController presentViewController:actionSheetController animated:YES completion:NULL];
Другие вопросы по тегам