2012-04-24 8 views
5

UINavigationControllerDelegate-Methoden werden beim Aufruf eines View-Controllers, der die aktuelle Ausrichtung nicht unterstützt, nicht aufgerufen.UINavigationControllerDelegate-Methoden nicht aufgerufen (Demo-Code auf GitHub)

Ich habe einen UINavigationController als root-View-Controller meiner App (erste Ansicht Controller in meinem Storyboard).

Lassen Sie sagen, ich mit diesem einen Viewcontroller A Push zur Orientierung:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    return (interfaceOrientation == UIInterfaceOrientationPortrait); 
} 

daher nicht unterstützen wir alle Landscape-Modus. Hinzu kommt, dass wir einen anderen Viewcontroller mit Code drücken:

@interface B : UIViewController <UINavigationControllerDelegate> 
@end 

@implementation B 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    return YES; // any orientation supported 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 
    UINavigationController *nc = (UINavigationController*)appDelegate.window.rootViewController; 
    nc.delegate = self; 
} 

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { 
    // not always called... 
} 

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated { 
    // not always called... 
} 
@end 

Nun, wenn ich mein iPhone im Hoch- und ich schieben View-Controller B oben auf A, über einige Berührungsereignis, dann tippen Sie auf die Schaltfläche „Zurück“ in Die Navbar, alles ist in Ordnung und die Delegate-Methoden werden aufgerufen (ich mache einige Sachen dort).

Aber, wenn ich Ansicht B ansicht, ich zu Landschaft drehen, und dann drücken Sie die Zurück-Taste, diese Delegate Methoden werden nicht aufgerufen !! Was ist der Zweck, einen Delegaten für den UINavigationController zu setzen, wenn die Methoden manchmal, aber nicht anders aufgerufen werden? Sicher mache ich etwas falsch.

Ich versuche, den Delegaten in andere Klasse, wie AppDelegate oder meine MainView, nichts zu ändern.

Irgendwelche Ideen?

Demo-Code hier:git://github.com/malaba/NavBarTest.git

Von einer grundlegenden Master-Detail-Vorlage, modifiziert wie oben.

Wie zeige ich meinen Standpunkt? Hier ist die Schritt-für-Schritt:

  1. eine Zeile hinzufügen in Master View (die + rechts oben)
  2. dann eine Linie berühren zu gehen, um Details
  3. Siehe Log in Ausgabe anzeigen zeigt sich
  4. Hit back button (beschriftet mit "Master"), wieder log erscheint.

Jetzt versuchen, das iPhone (oder Simulator) in Details Ansicht zu drehen, dann gehen Sie „zurück“ und sehen kein Protokoll zeigt sich ?!

Antwort

1

von Kaspar antworte, hier ist mein Code in Obj-C.

.h:

@interface ProperNavigationController : UINavigationController 

@end 

@interface ProperNavigationControllerDelegate : NSObject <UINavigationControllerDelegate> 
@property (assign, nonatomic) BOOL wasCalled; 
@end 

.m:

#import "ProperNavigationController.h" 

@interface ProperNavigationController() 
@property (strong, nonatomic) id<UINavigationControllerDelegate> oldDelegate; 
@property (strong, nonatomic) ProperNavigationControllerDelegate *myDelegate; 
@end 

@implementation ProperNavigationController 
@synthesize oldDelegate = _oldDelegate; 
@synthesize myDelegate = _myDelegate; 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    self.oldDelegate = self.delegate; 
    self.myDelegate = [ProperNavigationControllerDelegate new]; 
    self.delegate = self.myDelegate; 
} 

- (UIViewController *)popViewControllerAnimated:(BOOL)animated { 
    self.myDelegate.wasCalled = FALSE; 

    UIViewController *vc = [super popViewControllerAnimated:animated]; 

    if (!self.myDelegate.wasCalled) { 
     // if iOS did not call the delegate handler then we must do it 
     [self.myDelegate navigationController:self willShowViewController:self.topViewController animated:animated]; 
     [self.myDelegate navigationController:self didShowViewController:self.topViewController animated:animated]; 
    } 

    return vc; 
} 

@end 

@implementation ProperNavigationControllerDelegate 
@synthesize wasCalled = _wasCalled;  // flag that we use to track whether iOS calls the handlers or we have to 

- (id)init { 
    if (self = [super init]) { 
     _wasCalled = FALSE; 
    } 
    return self; 
} 

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { 
    ProperNavigationController *nc = (ProperNavigationController *)navigationController; 
    [nc.oldDelegate navigationController:navigationController willShowViewController:viewController animated:animated]; 
    self.wasCalled = TRUE; // signal that we have been called 
} 

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated { 
    ProperNavigationController *nc = (ProperNavigationController *)navigationController; 
    [nc.oldDelegate navigationController:navigationController didShowViewController:viewController animated:animated]; 
} 

@end 

es funktionieren.

Was denkst du? Und sollten wir einen Fehlerbericht ausfüllen?

2

Hallo war dies eine schwierige Frage für mich auch, bis ich diese Idee sah: http://www.hanspinckaers.com/custom-action-on-back-button-uinavigationcontroller

Wenn sowohl die Navigation und die TopViewController die gleiche Ausrichtung haben, dann IOS erstellt die folgende Aufrufsequenz den Code unten verwenden (Monotouch)

  • SomeTopViewController ViewWillDisappear
  • WillShowViewController Viewcontroller: der neue TopViewController
  • SomeTopViewController ViewDidDisappear
  • DidShowViewController Viewcontroller: Der neue TopViewController

Wenn die Navigation und die TopViewController haben unterschiedliche Orientierungen dann die Navigation Delegat ist nicht genannt, wie Sie beschrieben. Die Aufrufsequenz ist daher:

  • SomeTopViewController ViewWillDisappear
  • SomeTopViewController ViewDidDisappear

Der folgende Code reproduzieren die ios Sequenz Aufruf der PopViewControllerAnimated ‚Navigation überschrieben:

public class MyNavigationControllerDelegate : UINavigationControllerDelegate { 
    public MyNavigationControllerDelegate() : base() {} 

    public bool WasCalled {get;set;} // flag that we use to track whether iOS calls the handlers or we have to 

    public override void WillShowViewController(UINavigationController navigationController, UIViewController viewController, bool animated) { 
    Console.WriteLine("WillShowViewController viewController: {0}", viewController.GetType()); 
    WasCalled = true; // signal that we have been called 
    //.….. do your stuff 
    } 

    public override void DidShowViewController(UINavigationController navigationController, UIViewController viewController, bool animated) { 
    Console.WriteLine("DidShowViewController viewController: {0}", viewController.GetType()); 
    //.….. do your stuff 
    } 
} 

public partial class MyNavigationController : UINavigationController { 
    MyNavigationControllerDelegate navigationControllerDelegate; 

    public override void ViewDidLoad() { 
    base.ViewDidLoad(); 
    navigationControllerDelegate = new MyNavigationControllerDelegate(viewSelectionControl); 
    Delegate = navigationControllerDelegate; 
    } 

public override UIViewController PopViewControllerAnimated(bool animated) { 
    Console.WriteLine("PopViewControllerAnimated TopViewController.GetType: {0}", TopViewController.GetType()); 
    navigationControllerDelegate.WasCalled = false; // reset flag before we start the popsequence 

    UIViewController ctrl = base.PopViewControllerAnimated(animated); 

    AppDelegate.MainWindow.BeginInvokeOnMainThread(delegate { 
    if(!navigationControllerDelegate.WasCalled) { // if iOS did not call the delegate handler then we must do it 
     Delegate.WillShowViewController(this, TopViewController, animated); 
     navigationControllerDelegate.WasCalled = false; // reset flag to be used in the next DidShowViewController step of the popsequence 
     } 
    }); 

    Thread t = new Thread(() => RunPop(animated)); 
    tt.Start(); 

    return ctrl; 
} 

void RunPop(bool animated) { 
    Thread.Sleep(500); 
    AppDelegate.MainWindow.BeginInvokeOnMainThread(delegate { 
    if(!navigationControllerDelegate.WasCalled) { // if iOS did not call the delegate handler then we must do it 
     Delegate.DidShowViewController(this,TopViewController,animated); 
    } 
    }); 
} 

}

+1

was ist diese Sprache? Obj-C++? Ich übersetze jetzt ... – malaba

+0

Es ist C#, mit MonoTouch. –

Verwandte Themen