iPhone: 在横屏模式下,第一个addSubview后,UITableViewController不能正确旋转

4

这是一个关于it技术的Xcode项目,可以在github上找到。

当我将第二个及后续的UITableView添加为子视图时,它们无法正确旋转,因此显示为侧卧。这仅在模拟器中测试过。下面是一些代码:

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    ShellTVC* viewA = [[ShellTVC alloc] initWithTitle:@"View A"];
    ShellTVC* viewB = [[ShellTVC alloc] initWithTitle:@"View B"];

    // The first subview added will rotate to landscape correctly. 
    // Any subsequent subview added will not.

    // You may try this by various commentings and rearranging of these two statements.

    [window addSubview:[viewA tableView]];
    [window addSubview:[viewB tableView]];

    [window makeKeyAndVisible];
}

视图B显示为侧面。将viewB的addSubview注释掉,viewA就会正确显示。只对viewA这样做,viewB就会正确显示。

我没有通过NIB创建这些UITableViewControllers,但UIWindow是通过NIB创建的。

如果你想知道,ShellTVC是一个UITableViewController,并实现了这个方法:

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

另外,我已经在plist文件中将UIInterfaceOrientation设置为UIInterfaceOrientationLandscapeLeft。

可能与此相关的,但未得到回答的SO问题可以在这里这里找到。


请查看“iPhone横屏常见问题解答和解决方案”获取您的问题的答案:https://dev59.com/snA85IYBdhLWcg3wEPVL - Johannes Rudolph
1
或者,将您的手机升级到iOS 4.x。:\ 我只在3.x设备上遇到这种错误行为。 - AndrewS
6个回答

8

我认为我找到了一种方法——可能是正确的方法——来解决这个问题。

  1. 创建一个“主”UIViewController子类,实现shouldAutorotate...方法,并将其作为窗口上唯一的视图。
  2. 要在viewA和viewB之间切换,请使用dismissModalViewControllerAnimated:和presentModalViewController:animated:这两个方法在此主视图控制器上进行组合操作。

以下是一些代码:

// this doesn't really do much but implement shouldAutorotate...
@interface MasterViewController : UIViewController
@end

@implementation MasterViewController
- (BOOL) shouldAutorotateToInterfaceOrientation(UIInterfaceOrientation)interfaceOrientation {
     return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
@end

@interface MyAppDelegate : NSObject <UIApplicationDelegate> {
    MasterViewController* masterVC;
    UIViewController* activeTVC;
    UIViewController* onDeckTVC;
}
@end

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    UIViewController* masterVC = [[MasterViewController alloc] init];        
    activeTVC = [[ShellTVC alloc] initWithTitle:@"View A"];
    onDeckTVC = [[ShellTVC alloc] initWithTitle:@"View B"];
    [window addSubview:masterView.view];
    [window makeKeyAndVisible];
    [masterVC presentModalViewController:activeTVC animated:NO];
}

// you would call this to toggle between "View A" and "View B"
- (void)toggleTVC {
    UITableViewController *hold = activeTVC;
    activeTVC = onDeckTVC;
    onDeckTVC = hold;
    [masterVC dismissModalViewControllerAnimated:NO];   
    [masterVC presentModalViewController:activeTVC animated:NO];
}

为什么这个代码能够工作?

  1. 所有方向的更改都通过视图控制器而不是视图进行。

  2. 据我所知,添加到窗口的第一个视图或子视图会得到一些特殊的处理。如果该视图有视图控制器,窗口会找到它。

也就是说,只针对第一个子视图,您可以将此代码视为:

[window addSubview:masterVC.view];

像这样执行(不是真实的方法!):
[window addSubview:masterVC.view withViewController:masterVC];

我对此的了解不超过这个程度。我发现我可以在第一个子视图中做到这一点,但在其他子视图中却不能,这让我非常困惑。欢迎提供更多信息,并请告诉我这是否对您有帮助。


1
这个问题似乎在iOS 4.x中已经解决了,因为我正在开发一个iPad应用程序,一切都很好,直到我们发现我们必须支持3.2,并且我遇到了同样的问题。这个解决方案对我非常有效。谢谢! - Christopher Pickslay

1

显然,如果将viewB作为viewA的子视图添加,它将被正确旋转。这对于我的项目来说不是一个很好的解决方案,但看起来这可能是唯一的解决方法。


0

很遗憾,当方向发生变化时,您的子视图只会被询问它们支持哪些方向。

所以如果我知道方向已经改变,我最终会在将新的视图控制器推入栈之前设置方向:

[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait]; 

是的,这是一个不被支持的调用。


尝试将此代码作为 applicationDidFinishLaunching 的第一行,但没有起作用。 - Clay Bridges
如果您想控制整个应用程序,可以编辑Info.plist文件,告诉它默认方向是什么。查找UIInterfaceOrientation键。 - Epsilon Prime
谢谢,是的,我做了那个。根据原始帖子中的描述,“另外,我已经在plist文件中将UIInterfaceOrientation设置为UIInterfaceOrientationLandscapeLeft”。 - Clay Bridges

0

你可以使用UIApplication对象来强制设定特定的设备方向。

[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];

尝试将其作为applicationDidFinishLaunching的第一行,但没有起作用。还尝试在传递的UIApplication参数上设置它,但也没有起作用。 - Clay Bridges

-1

这应该可以工作。

- (void)viewDidLoad {
    if (([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft) || 
        ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight)) 

    {
        self.view.frame = CGRectMake(0, 0, 1024, 748);

    } else {
        self.view.frame = CGRectMake(0, 0, 768, 1004);
    }
}

-1

是的,我相信您必须通过拥有多个XIB来解决这个问题。我记得在过去阅读的一本书中看到了这个解决方案。如果不行,您可以尝试调整视图中对象的翻译和位置...最好使用单独的XIB。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接