iPhone:仅在横向上,在第一个addSubview之后,UITableViewController无法正常旋转

StackOverflow https://stackoverflow.com/questions/1632117

  •  06-07-2019
  •  | 
  •  

github 上提供了一个最小的说明性Xcode项目。

在我的UIWindow上,当我添加第二个(和后续的)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];
}

viewB出现在侧面。注释掉viewB的addSubview,viewA正确显示。仅对viewA执行此操作,并且viewB正确显示。

我不是通过NIB创建这些UITableViewControllers,尽管UIWindow是。

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

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

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

可能相关 - 也没有答案 - 提出问题此处此处

有帮助吗?

解决方案

我想我找到了一种方法 - 可能是正确的方法 - 来做到这一点。

  1. 创建“主人” UIViewController子类,它实现了shouldAutorotate ...,并将其添加为窗口上的唯一视图。
  2. 要在viewA或viewB之间切换,请使用dismissModalViewControllerAnimated的组合:& presentModalViewController:animated:在这个主视图控制器上。
  3. 以下是一些代码:

    // 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. 据我所知,您添加到窗口的第一个视图或子视图会有一些特殊的味道。如果该视图具有视图控制器,则窗口会将其计算出来。

    3. 也就是说,对于第一个子视图,您可以考虑以下代码:

      [window addSubview:masterVC.view];
      

      做这样的事情(不是真正的方法!):

      [window addSubview:masterVC.view withViewController:masterVC];
      

      我对此不了解。我发现我可以用第一个子视图执行此操作,而不是其他子视图,这非常令人困惑。欢迎更多信息,如果这对您有所帮助,请告诉我。

其他提示

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

不幸的是,只会询问您的子视图在方向发生变化时支持的方向。

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

[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait]; 

是的,这是一个不受支持的电话。

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

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

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

这应该有用。

- (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);
    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top