web-dev-qa-db-de.com

Der PräferenzStatusBarHidden von UIViewController funktioniert nicht

Ich versuche, die Statusleiste für einen meiner View-Controller auszublenden (wenn er modal angezeigt wird). Wenn ich den View Controller präsentiere, soll die Statusleiste ausgeblendet und dann zurückgegeben werden, wenn sie abgelehnt wird.

Ich habe den folgenden Code zum dargestellten View-Controller hinzugefügt

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

Ich habe auch die Schlüssel in der Info.plist-Datei wie folgt festgelegt:

<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>

Nach meinem Verständnis sollte dies alles sein, um diese Arbeit durchzuführen. 

Ich verwende auch einen benutzerdefinierten Animationscontroller, um Präsentationen durchzuführen, die dem UIViewControllerAnimatedTransitioning-Protokoll entsprechen. In der animateTransition:-Implementierung habe ich versucht, manuell prefersStatusBarHidden aufzurufen, gefolgt von setNeedsStatusBarAppearanceUpdate, um sicherzustellen, dass der Aufruf erfolgt, die Statusleiste bleibt jedoch erhalten.

Alle Ideen, warum dies geschieht, würden wir begrüßen. Ich habe StackOverflow durchsucht, aber es scheint, dass niemand dieses Problem hatte. Alle akzeptierten Antworten beziehen sich auf den Aufruf von setNeedsStatusBarAppearanceUpdate, den ich bereits mache.

EDIT - Der folgende Code scheint jetzt WORK wie gewünscht zu sein 

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
    if (self.isPresenting) {
        UIView *containerView = [transitionContext containerView];

        UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

        toViewController.view.frame = containerView.frame;

        [containerView addSubview:toViewController.view];

        // Ask the presented controller whether to display the status bar
        [toViewController setNeedsStatusBarAppearanceUpdate];

        [UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionCurveEaseIn animations:^{
            toViewController.view.alpha = 1.0f;
            fromViewController.view.alpha = 0.0f;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
        }];
    }
    else {
        // do the reverse
        UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

        [UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionCurveEaseIn animations:^{
            toViewController.view.alpha = 1.0f;
            fromViewController.view.alpha = 0.0f;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
            // Once dismissed - ask the presenting controller if the status bar should be presented
            [toViewController setNeedsStatusBarAppearanceUpdate];
        }];
    }
}

....

// PresentingController.m
- (BOOL)prefersStatusBarHidden
{
    if (self.presentedViewController) {
        return YES;
    }
    return NO;
}

// PresentedController.m
- (BOOL)prefersStatusBarHidden
{
    return YES;
}
40
Taz

In iOS7 gibt es tatsächlich eine neue Eigenschaft für UIViewController mit dem Namen modalPresentationCapturesStatusBarAppearance. Apple iOS Referenz.

Der Standardwert ist NO.

Wenn Sie einen View-Controller durch Aufrufen der Methode presentViewController: animated: completion: präsentieren, wird die Darstellung der Statusleiste nur dann vom präsentierten View-Controller an den präsentierten View-Controller übertragen, wenn der modalPresentationStyle-Wert des dargestellten Controllers UIModalPresentationFullScreen ist. Wenn Sie diese Eigenschaft auf YES setzen, geben Sie die Darstellung der Statusleiste der angezeigten View Controller-Steuerelemente an, auch wenn sie nicht im Vollbildmodus angezeigt wird.

Das System ignoriert den Wert dieser Eigenschaft für einen Ansichts-Controller, der im Vollbildmodus angezeigt wird.

Für einen anderen Präsentationsstil als den normalen Vollbildmodus (z. B. UIModalPresentationCustom) muss dieses gesetzt werden, wenn Sie die Statusleiste erfassen möchten. Um es zu verwenden, müssen Sie es nur auf dem angezeigten View-Controller auf YES setzen:

toVC.modalPresentationCapturesStatusBarAppearance = YES;
106
David Liu

Ich gehe davon aus (gebildet, aber immer noch eine Vermutung), dass dies daran liegt, dass, wenn Sie einen präsentierten Ansichtscontroller mit einem benutzerdefinierten Übergang ausführen, in iOS 7 der alte Ansichtscontroller immer noch vorhanden ist . Deshalb wird es wohl noch ein Mitspracherecht geben.

Sie könnten sogar einen Haltepunkt in sein prefersStatusBarHidden setzen, um zu sehen; Sie müssen es implementieren, wenn es nicht implementiert ist. Die Standardeinstellung ist NEIN. Wenn Sie diese Einstellung aufrufen, wird Ihr Ergebnis dadurch erklärt.

Wenn ich recht habe, müssten Sie den prefersStatusBarHidden des alten Ansichtscontrollers implementieren, um zwei unterschiedliche Antworten zu geben, je nachdem, ob er vorhanden ist a presentedViewController oder nicht.

EDIT Ich habe das jetzt bestätigt. Es ist noch schlimmer als ich dachte; In meinen Tests wird das prefersStatusBarHidden des zweiten View-Controllers überhaupt nicht aufgerufen. Das Ganze liegt in den Händen des First View Controllers. Dies ist sinnvoll, da der First View Controller, wie gesagt, nie verschwindet. Bei einer benutzerdefinierten Präsentationsanimation ist der zweite Ansichts-Controller dem ersten untergeordnet, da die zweite Ansicht teilweise über der ersten Ansicht schweben kann.

Daher müssen Sie die Statusleiste vollständig vom ersten Ansichtscontroller aus steuern. Sie können den Aufruf von prefersStatusBarHidden veranlassen, indem Sie [self setNeedsStatusBarAppearanceUpdate] Aufrufen. Sie müssen je nach den Umständen eine andere Antwort geben. Das kann etwas schwierig sein. Hier ist eine einfache Implementierung, die jedoch möglicherweise nicht alle Fälle abdeckt:

// ViewController1:

-(void)setHide:(NSNumber*)yn {
    self->hide = [yn boolValue]; // a BOOL ivar
    [self setNeedsStatusBarAppearanceUpdate];
}
-(BOOL)prefersStatusBarHidden {
    return self->hide;
}
- (IBAction)doButton:(id)sender {
    self->hide = YES;
    [self setNeedsStatusBarAppearanceUpdate];
    [self presentViewController:[ViewController2 new] animated:YES completion:nil];
}

// ==========

// ViewController2:

- (IBAction)doButton:(id)sender {
    [self.presentingViewController setValue:NO forKey:@"hide"];
    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
17
matt

Wenn es nicht funktioniert und Ihr UIViewController ein untergeordnetes Element in UINavigationController ist, ist dieser Code möglicherweise eine Lösung für Sie.

open override var prefersStatusBarHidden: Bool {
    return topViewController?.prefersStatusBarHidden ?? super.prefersStatusBarHidden
}

Grundsätzlich verwendet der UINavigationController seinen eigenen prefersStatusBarHidden Wert, aber in meinem Fall wollte ich diesen durch die hierarchische Eigenschaft des Controllers in der Draufsicht überschreiben.

0
Konrad Siemczyk

Sie können dies zu info.plist hinzufügen

"Controller-basierte Statusleiste anzeigen" und den Wert auf "Nein" setzen

0
zuyao88