2012-04-24 12 views
5

UINavigationControllerDelegateメソッドは、現在の方向をサポートしていないView Controllerにポップするときに呼び出されません。UINavigationControllerDelegateメソッドが呼び出されない(githubのデモコード)

私のアプリのルートビューコントローラ(私のストーリーボードの初期ビューコントローラ)としてUINavigationControllerがあります。

レッツは、私はオリエンテーションのためにこれでのViewController Aを押して言う:

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

そこで我々はすべてのランドスケープモードをサポートしていません。その上のコードで別のViewControllerを押してみましょう:私は肖像画に私のiPhoneを持っていると私はAの上にビューコントローラのBを押した場合

@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 

は今、いくつかのタッチイベントを経て、その後に「戻る」ボタンをタッチnavbar、すべてが問題なく、デリゲートメソッドが呼び出されます(私はそこにいくつかのことを行います)。

ビューBを表示しているときにランドスケープに回転してから戻るボタンを押すと、そのデリゲートメソッドは呼び出されません。 UINavigationControllerのデリゲートを設定するポイントは何ですか?メソッドは他のものではなく時々呼び出されますか?確かに私は何か間違っている。

私はAppDelegateやMainViewのような他のクラスにデリゲートを置こうとしますが、何も変わりません。

アイデア?ここ

デモコード:git://github.com/malaba/NavBarTest.git

基本的なマスター・ディテールテンプレートから、ちょうど上記のように修正。

ポイントを表示するには?ここでは、ステップバイステップである:(+の右上)

    1. マスタービューでいくつかの行を追加します。その後、詳細に行くためのラインに触れ
    2. を示す出力に
    3. 参照ログを表示
    4. 「戻る」ボタン(「マスター」と表示)を押して、再度ログを表示します。今

    、その後、「背中」に行くと現れてなしログを参照してください詳細ビューでiPhone(またはシミュレータ)を回転させるようにしてみてください!

  • 答えて

    1

    はKasparの答えで、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 
    

    それが動作します。

    あなたはどう思いますか?そして、バグレポートに記入する必要がありますか?

    2

    こんにちは私はこのアイデアを見るまで、これはあまりにも私にとってはタフな問題でした:NavigationControllerとTopViewControllerの両方が同じ方向性を持っている場合http://www.hanspinckaers.com/custom-action-on-back-button-uinavigationcontroller

    は、IOSは、以下のコード(MonoTouchで)

    を使用して、次の呼び出しシーケンスを作成し、
    • SomeTopViewController ViewWillDisappear
    • WillShowViewControllerのViewController:新しいTopViewController
    • SomeTopViewController ViewDidDisappear
    • DidShowViewControllerのViewController:新しいTopViewController

    NavigationControllerとTopViewControllerが異なる向きを有する、その後NavigationControllerデリゲートは、あなたが説明するように呼ばないです。呼び出しシーケンスは、したがってある:

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

    }

    :SomeTopViewController ViewWillDisappear
  • SomeTopViewController ViewDidDisappear
  • 次のコードは、IOSがNavigationController」PopViewControllerAnimatedをオーバーライドすることによってシーケンスを呼び出す再現

    +1

    この言語は何ですか? Obj-C++?私は今翻訳しています... – malaba

    +0

    MonoTouchを使っているのはC#です。 –

    関連する問題