Представление контроллера представления без изменения цвета строки состояния, например UIAlertController

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

Контроллер представления имеет modalPresentationStyle = .Custom и анимируется с помощью делегата перехода и настраиваемого контроллера представления. Помимо анимации переходов, у них нет настраиваемых действий, управляющих презентацией.

У меня проблема в том, что всякий раз, когда представлен контроллер представления, он меняет цвет строки состояния на черный. Я мог бы переопределить preferredStatusBarStyle, чтобы он всегда возвращал .LightContent, но иногда этот контроллер представления отображается поверх контроллера представления с помощью .Default, и я тоже не хочу его менять. В принципе, я хочу вести себя так же, как UIAlertController.

Снимок экрана, показывающий представленный контроллер представления, вызывающий темное содержимое строки состояния

Я попытался настроить контроллер представления, чтобы переместить представленный контроллер представления из области строки состояния:

private class SEUIProgressControllerPresentationController: UIPresentationController {

    override func shouldPresentInFullscreen() -> Bool {
        return false
    }

    private override func frameOfPresentedViewInContainerView() -> CGRect {
        return super.frameOfPresentedViewInContainerView().insetBy(dx: 40, dy: 100)
    }

    ...
}

Эти настройки действительно перемещают верхнюю часть представленного контроллера из строки состояния, но строка состояния по-прежнему затрагивается. Есть ли свойство, которое мне не хватает, чтобы мой контроллер представления не обновлял стиль строки состояния?


person Brian Nickel♦    schedule 15.01.2016    source источник


Ответы (1)


Обновлять

Похоже, это было исправлено в iOS 10. Поведение по умолчанию - игнорировать правила строки состояния из представленного контроллера представления , если либо представленный контроллер представления не имеет modalPresentationCapturesStatusBarAppearance == true, либо вы используете один из нескольких встроенных контроллеры презентаций, которые простираются до области строки состояния (не .custom).

По сути, поведение custom было изменено на отказ по умолчанию, а не на принудительное включение.


Для iOS 9.x и ниже

После долгих поисков внутренняя логика установки цвета строки состояния приложения выглядит так:

var viewController = window.rootViewController!

while let presentedViewController = viewController.valueForKey("_presentedStatusBarViewController") as? UIViewController {
    viewController = presentedViewController
}

while let childViewController = viewController.childViewControllerForStatusBarStyle() {
    viewController = childViewController
}

let style = viewController.preferredStatusBarStyle()

Свойство _presentedStatusBarViewController контроллера представления назначается во время презентации на основе значения частного метода _shouldChangeStatusBarViewController() его контроллера представления. Реализация этого метода по умолчанию - вернуть true, а _UIAlertControllerPresentationController и несколько других контроллеров представления возвращают false.

Это означает, что самый прямой способ не менять эту строку состояния - просто добавить этот метод в мой контроллер презентации:

private class SEUIProgressControllerPresentationController: UIPresentationController {

    @objc func _shouldChangeStatusBarViewController() -> Bool {
        return false
    }

    ...
}

К сожалению, это не пройдет проверку в App Store.

Вместо этого я воссоздаю логику, которая будет применяться к представляющему контроллеру представления в моем контроллере представления:

public class SEUIProgressController: UIViewController {

    ...
    public override func preferredStatusBarStyle() -> UIStatusBarStyle {

        guard var targetViewController = presentingViewController else {
            return .LightContent
        }

        while let parentViewController = targetViewController.parentViewController {
            targetViewController = parentViewController
        }

        while let childViewController = targetViewController.childViewControllerForStatusBarStyle() {
            targetViewController = childViewController
        }

        return targetViewController.preferredStatusBarStyle()
    }

    public override func prefersStatusBarHidden() -> Bool {

        guard var targetViewController = presentingViewController else {
            return false
        }

        while let parentViewController = targetViewController.parentViewController {
            targetViewController = parentViewController
        }

        while let childViewController = targetViewController.childViewControllerForStatusBarHidden() {
            targetViewController = childViewController
        }

        return targetViewController.prefersStatusBarHidden()
    }
}
person Brian Nickel♦    schedule 15.01.2016
comment
Да, исправлено, начиная с iOS 10, и это странная проблема, если вы используете светлую строку состояния и вам нужно создать модальное предупреждение. Вам нужно только установить: controllerToPresent.modalPresentationCapturesStatusBarAppearance = true, спасибо. - person José Miguel Galván; 11.10.2018