ViewWillAppear 没有被 UISplitViewController 调用
背景与目标:我有一个基于 UISplitViewController 的 iPad 应用程序 - 到目前为止它支持 4 个方向,但现在我想将其锁定为仅横向。 我更改了左视图控制器的shouldAutorotateToInterfaceOrientation以仅支持横向模式,但这会阻止调用它的viewWillAppear。
详细信息:我的 iPad 的视图控制器组织如下:
window
`-- splitVC (UISplitViewController)
`-- rootNav (UINavigationController)
`-- hvc (HostManagerViewController, derived from UIViewController)
`-- detailViewController (DetailViewController, derived from UIViewController)
这是在应用程序委托中实现的,如下所示:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
HostManagerViewController *hvc = [[[HostManagerViewController alloc]
initWithNibName:nil bundle:nil] autorelease];
self.detailViewController = [[[DetailViewController alloc]
initWithNibName:nil bundle:nil] autorelease];
UINavigationController *rootNav = [[[UINavigationController alloc]
initWithRootViewController:hvc] autorelease];
UISplitViewController *splitVC= [[[UISplitViewController alloc] init] autorelease];
[splitVC setViewControllers:[NSArray arrayWithObjects:rootNav,
detailViewController, nil]];
splitVC.delegate = detailViewController;
[window addSubview:splitVC.view];
[window setRootViewController:splitVC];
return YES;
}
当 DetailViewController.m
和 HostManagerViewController.m 都被调用时,
包含viewWillAppear
被调用
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
Console output:
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Hostmanager: Viewdidload
Should rotate called to hostmanager with 1
Hostmanager: viewwillappear
但是当我将 HostManagerViewController 的代码更改为
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (UIInterfaceOrientationIsLandscape(interfaceOrientation));
}
HostManagerViewController 的“viewWillAppear”时,不会调用该代码。控制台输出
Should rotate called to hostmanager with 1 (1 is the numeric value of interfaceOrientation)
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Should rotate called to hostmanager with 3
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Hostmanager: Viewdidload
Should rotate called to hostmanager with 1
Info.plist 中仅支持横向模式
编辑:插入 NSLog 消息以跟踪 shouldAutorotateToInterfaceOrientation
、viewWillAppear
和 ViewDidLoad
Background & Objective: I have a UISplitViewController based iPad app - till now it supported 4 orientations but now I want to lock it down to only landscape.
I changed shouldAutorotateToInterfaceOrientation
of the left view controller to support only landscape mode, but this stops its viewWillAppear
from getting called.
Details: My iPad's view controllers are organized as below:
window
`-- splitVC (UISplitViewController)
`-- rootNav (UINavigationController)
`-- hvc (HostManagerViewController, derived from UIViewController)
`-- detailViewController (DetailViewController, derived from UIViewController)
This is implemented in the App Delegate as below:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
HostManagerViewController *hvc = [[[HostManagerViewController alloc]
initWithNibName:nil bundle:nil] autorelease];
self.detailViewController = [[[DetailViewController alloc]
initWithNibName:nil bundle:nil] autorelease];
UINavigationController *rootNav = [[[UINavigationController alloc]
initWithRootViewController:hvc] autorelease];
UISplitViewController *splitVC= [[[UISplitViewController alloc] init] autorelease];
[splitVC setViewControllers:[NSArray arrayWithObjects:rootNav,
detailViewController, nil]];
splitVC.delegate = detailViewController;
[window addSubview:splitVC.view];
[window setRootViewController:splitVC];
return YES;
}
viewWillAppear
gets called when both DetailViewController.m
and HostManagerViewController.m
contain
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
Console output:
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Hostmanager: Viewdidload
Should rotate called to hostmanager with 1
Hostmanager: viewwillappear
But when I change HostManagerViewController
's code to
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (UIInterfaceOrientationIsLandscape(interfaceOrientation));
}
then 'viewWillAppear` of HostManagerViewController is not invoked. Console output
Should rotate called to hostmanager with 1 (1 is the numeric value of interfaceOrientation)
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Should rotate called to hostmanager with 3
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Hostmanager: Viewdidload
Should rotate called to hostmanager with 1
Only Landscape modes are supported in the Info.plist
EDIT: Inserted NSLog messages to track shouldAutorotateToInterfaceOrientation
, viewWillAppear
and ViewDidLoad
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我询问您使用的是哪个 iOS 版本,因为我尝试创建您的问题的简单重现,并发现 4.3 和 5.0 之间的行为有所不同。它实际上确实在 5.0 中进行了所有正确的调用。我相信这只是 UISplitviewController 的一个错误。 Splitview 控制器有很多问题。 aopsfan的回答并没有解决问题(我已经证实了这一点)。我建议对 uisplitviewcontroller 进行子类化,并重写 splitview 控制器的 viewwillappear、viewdidappear ,如下所示:
您必须检查版本号,以免两次调用 viewDidAppear 。
或者如果可以的话,就使用 5.0 或更高版本,因为该错误似乎已修复。
I asked what iOS version you were using because I tried to create a simple reproduction of your problem and found the behavior differs between 4.3 and 5.0. It actually does make all the correct calls in 5.0. I believe this to simply be a bug with the UISplitviewController. Splitview controller was quite buggy. aopsfan's answer does not solve the problem (I have confirmed this). I would suggest subclassing uisplitviewcontroller, and overriding the splitview controller's viewwillappear, viewdidappear like so:
You have to check the version number so that you don't make the viewDidAppear call twice.
Or just go with 5.0 or above if you can, since the bug seems to be fixed.
基本上,由于
UISplitViewController
有两个部分,因此您需要一个 shouldAutorotate 的通用实现。我认为单独处理视图控制器的旋转可能会导致一些奇怪的副作用 - 但请注意,我无法复制您的viewWillAppear
问题,所以这个解决方案实际上是一个猜测。我建议创建一个非常简单的 UISplitViewController 子类。将其命名为“SplitViewController”,并在其
.m
文件中,删除除 shouldAutorotate 之外的所有内容,如下所示:现在更改
HostManagerViewController
和DetailViewController 中的 shouldAutorotate 代码
返回:现在,在您的应用程序委托中,使用此类而不是
UISplitViewController
。这应该(可能)解决你的问题。Basically, since a
UISplitViewController
has two parts, you need a universal implementation of shouldAutorotate. I suppose that tackling the rotation of the view controllers individually can cause some weird side affects--though please take note that I was not able to replicate yourviewWillAppear
issue, so this solution is really a guess.I would recommend making a dead-simple subclass of
UISplitViewController
. Name it "SplitViewController", and in it's.m
file, delete everything except shouldAutorotate, which will look like this:Now change your shouldAutorotate code in
HostManagerViewController
andDetailViewController
back to:Now, in your app delegate, use this class instead of
UISplitViewController
. This should (may) fix your problem.您将UISplitViewControler的委托设置为detailViewController
我认为阻止旋转的最佳位置将在DetailViewController中而不是在HostManagerViewController中。我将更改 HostManagerViewController 中的 -shouldAutorotateToInterfaceOrientation 以始终返回 YES,并在 DetailViewController 中添加:
You set the delegate of the UISplitViewControler to the detailViewController
I think the best place to block the rotations will be in the DetailViewController and not in the HostManagerViewController. I would change the - shouldAutorotateToInterfaceOrientation in the HostManagerViewController to return allways YES and in the DetailViewController i would add: