ViewWillAppear 没有被 UISplitViewController 调用

发布于 2024-12-11 23:51:52 字数 3399 浏览 0 评论 0原文

背景与目标:我有一个基于 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.mHostManagerViewController.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 消息以跟踪 shouldAutorotateToInterfaceOrientationviewWillAppearViewDidLoad

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

贱贱哒 2024-12-18 23:51:52

我询问您使用的是哪个 iOS 版本,因为我尝试创建您的问题的简单重现,并发现 4.3 和 5.0 之间的行为有所不同。它实际上确实在 5.0 中进行了所有正确的调用。我相信这只是 UISplitviewController 的一个错误。 Splitview 控制器有很多问题。 aopsfan的回答并没有解决问题(我已经证实了这一点)。我建议对 uisplitviewcontroller 进行子类化,并重写 splitview 控制器的 viewwillappear、viewdidappear ,如下所示:

#import "testSplitViewController.h"

@implementation testSplitViewController

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    NSString *reqSysVer = @"5.0";
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
    if ([currSysVer compare:reqSysVer options:NSNumericSearch] == NSOrderedAscending)
        [[[self viewControllers] objectAtIndex:0] viewWillAppear:animated];
}

-(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    NSString *reqSysVer = @"5.0";
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
    if ([currSysVer compare:reqSysVer options:NSNumericSearch] == NSOrderedAscending)
        [[[self viewControllers] objectAtIndex:0] viewDidAppear:animated];
}
@end

您必须检查版本号,以免两次调用 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:

#import "testSplitViewController.h"

@implementation testSplitViewController

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    NSString *reqSysVer = @"5.0";
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
    if ([currSysVer compare:reqSysVer options:NSNumericSearch] == NSOrderedAscending)
        [[[self viewControllers] objectAtIndex:0] viewWillAppear:animated];
}

-(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    NSString *reqSysVer = @"5.0";
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
    if ([currSysVer compare:reqSysVer options:NSNumericSearch] == NSOrderedAscending)
        [[[self viewControllers] objectAtIndex:0] viewDidAppear:animated];
}
@end

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.

栖迟 2024-12-18 23:51:52

基本上,由于 UISplitViewController 有两个部分,因此您需要一个 shouldAutorotate 的通用实现。我认为单独处理视图控制器的旋转可能会导致一些奇怪的副作用 - 但请注意,我无法复制您的 viewWillAppear 问题,所以这个解决方案实际上是一个猜测。

我建议创建一个非常简单的 UISplitViewController 子类。将其命名为“SplitViewController”,并在其 .m 文件中,删除除 shouldAutorotate 之外的所有内容,如下所示:

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

现在更改 HostManagerViewControllerDetailViewController 中的 shouldAutorotate 代码 返回:

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

现在,在您的应用程序委托中,使用此类而不是 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 your viewWillAppear 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:

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

Now change your shouldAutorotate code in HostManagerViewController and DetailViewController back to:

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

Now, in your app delegate, use this class instead of UISplitViewController. This should (may) fix your problem.

二手情话 2024-12-18 23:51:52

您将UISplitViewControler的委托设置为detailViewController

splitVC.delegate = detailViewController;

我认为阻止旋转的最佳位置将在DetailViewController中而不是在HostManagerViewController中。我将更改 HostManagerViewController 中的 -shouldAutorotateToInterfaceOrientation 以始终返回 YES,并在 DetailViewController 中添加:

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

You set the delegate of the UISplitViewControler to the detailViewController

splitVC.delegate = 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:

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (UIInterfaceOrientationIsLandscape == interfaceOrientation);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文