Thomas Bandt

Über mich | Kontakt | Archiv

iOS 7: "Corrupted Navigation Bar" mit Swipe-Back-Gesten

Apple hat mit iOS 7 "frei Haus" eine Gestensteuerung eingebaut, mit deren Hilfe der Nutzer über ein Wischen vom linken Rand einen zuvor geöffneten Dialog wieder schließen kann.

Voraussetzung hier ist, dass der Dialog nicht modal angezeigt, sondern auf den Stack des Navigation Controllers gepusht wird. Verwendet man eigene NavigationItems, braucht es etwas Nachhilfe, um die Funktion zu aktivieren, da der Standard-Back-Button nicht angezeigt wird, mit dem das Feature aktiviert wird:

InteractivePopGestureRecognizer.Delegate = new UIGestureRecognizerDelegate();
InteractivePopGestureRecognizer.Enabled = true;

Das Problem: verwendet man eben einen eigenen Back-Button oder schließt man Dialoge manuell, kommt es immer wieder zu Meldungen der Art "nested pop animation can result in corrupted navigation bar" und "Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.".

Apple formuliert das im Konjunktiv, tatsächlich ist es zu diesem Zeitpunkt meist schon zu spät:

Um das zu vermeiden, ist es notwendig vor dem Pushen den GestureRecognizer zu deaktivieren und ihn erst nach Beendigung wieder zu aktivieren, wie hier beschrieben.

Die Objective-C-Lösung findet sich in dem verlinkten Post, die MonoTouch-Variante folgt hier:

public class WSNavigationController : UINavigationController
{
    WSNavigationControllerDelegate _delegate;

    public WSNavigationController(UIViewController rootViewController) : base(rootViewController)
    {
        InteractivePopGestureRecognizer.Delegate = new UIGestureRecognizerDelegate();

        _delegate = new WSNavigationControllerDelegate();
        Delegate = _delegate;
    }

    public override void ViewWillAppear(bool animated)
    {
        base.ViewWillAppear(animated);

        _delegate.ViewControllerPushed += ViewControllerPushed;
    }

    public override void ViewDidDisappear(bool animated)
    {
        base.ViewDidDisappear(animated);

        _delegate.ViewControllerPushed -= ViewControllerPushed;
    }

    public override void PushViewController(UIViewController viewController, bool animated)
    {
        if (InteractivePopGestureRecognizer != null &&
            RespondsToSelector(new Selector("interactivePopGestureRecognizer")))
        {
            InteractivePopGestureRecognizer.Enabled = false;
        }

        base.PushViewController(viewController, animated);
    }

    private void ViewControllerPushed(object sender, EventArgs e)
    {
        if (InteractivePopGestureRecognizer != null &&
            RespondsToSelector(new Selector("interactivePopGestureRecognizer")))
        {
            InteractivePopGestureRecognizer.Enabled = true;
        }
    }

    public class WSNavigationControllerDelegate : UINavigationControllerDelegate
    {
        public event EventHandler ViewControllerPushed;

        public override void DidShowViewController(UINavigationController navigationController, UIViewController viewController, bool animated)
        {
            ViewControllerPushed(this, EventArgs.Empty);
        }
    }
}

Viel Spaß beim Wischen ;-).



« Zurück  |  Weiter »