弹出到不支持当前方向的视图控制器时未调用的UINavigationControllerDelegate方法。
我有一个UINavigationController作为我的应用程序的根视图控制器(我的Storyboard中的初始视图控制器)。
假设我将ViewController A推送到方向:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
因此我们不支持任何横向模式。最重要的是,让我们使用代码推送另一个ViewController:
@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
现在,如果我的iPhone是纵向的,我将视图控制器B推到A顶部,通过一些触摸事件,然后触摸导航栏中的“后退”按钮,一切都很好,并调用委托方法(我做那里的一些东西)。
但是,如果,当我正在查看视图B时,我旋转到横向,然后点击后退按钮,那些委托方法不会被调用!!如果有时调用方法而不调用其他方法,那么为UINavigationController设置委托有什么意义呢?当然我做错了。
我尝试将委托放在其他类中,比如AppDelegate或我的MainView,没有任何改变。
有什么想法吗?
演示代码: git://github.com/malaba/NavBarTest.git
从基本的Master-Detail模板中进行修改,如上所述。
如何表明我的观点?这是一步一步:
现在尝试在详情视图中旋转iPhone(或模拟器),然后“返回”并看到无日志出现?!
答案 0 :(得分:2)
嗨,这对我来说也是一个棘手的问题,直到我看到这个想法:http://www.hanspinckaers.com/custom-action-on-back-button-uinavigationcontroller
当NavigationController和TopViewController具有相同的方向时,IOS使用以下代码(monotouch)创建以下调用序列
当NavigationController和TopViewController具有不同的方向时,导航控制委托是不,如您所述。因此呼叫顺序是:
以下代码通过覆盖NavigationController的PopViewControllerAnimated来重现ios调用序列:
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 :(得分: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
它有效。
你怎么看?我们应该填写错误报告吗?