为什么UITabBarController在viewWillTransitionToSize中为隐藏视图提供了错误的大小?

时间:2014-11-20 00:39:44

标签: ios uitabbarcontroller

在iOS 8中,我移动我的代码依靠viewWillTransitionToSize调整我在UITabBarController下的viewControllers。但是,当当前未显示视图时,传递给它的大小不正确。

我写了一个小程序来隔离问题。它只是创建两个VC,标记它们,将它们放在TabBarController中,然后报告传递给viewWillTransitionToSize的大小。如果要重新创建它,可以使用以下代码替换虚拟项目AppDelegate.m。

输出低于程序。我做错了什么,或者是否有解决方法来获得正确的即将到来的尺寸?

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

@interface MyViewController : UIViewController

@property (strong, nonatomic) NSString * detailItem;

@end

@implementation MyViewController

- (void)viewWillTransitionToSize:(CGSize)size
       withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
    NSLog(@"%@ will transition from %@ to %@",self.detailItem, NSStringFromCGSize(self.view.frame.size), NSStringFromCGSize(size));
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
}
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    MyViewController * firstVC = [[MyViewController alloc] initWithNibName:nil bundle:nil];
    firstVC.detailItem = @"Bookmark controller";
    firstVC.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem: UITabBarSystemItemBookmarks tag:0];

    MyViewController *secondVC = [[MyViewController alloc] initWithNibName:nil bundle:nil];
    secondVC.detailItem = @"History controller";
    secondVC.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem: UITabBarSystemItemHistory tag:1];

    UITabBarController * tabBarController = [[UITabBarController alloc] initWithNibName:nil bundle:nil];
    [tabBarController setViewControllers: @[firstVC, secondVC]];

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.rootViewController =  tabBarController;
    [self.window makeKeyAndVisible];

    return YES;
}


@end

输出如下:

<<starting in Bookmark VC in Portrait; transition to Landscape>>
Bookmark controller will transition from {375, 667} to {667, 375}  <<Correct>>
History controller  will transition from {375, 667} to {0, 0}      <<Very wrong>>

<<transition back to Portrait>>
Bookmark controller will transition from {667, 375} to {375, 667}  <<Correct>>
History controller  will transition from {375, 667} to {667, 375}  <<Wrong>>

<<switch to History tab; transition to Landscape>>
Bookmark controller will transition from {375, 667} to {375, 667}  <<Wrong>>
History controller  will transition from {375, 667} to {667, 375}  <<Correct; note prev wrong size is now correct without notification>>

<<transition back to Portrait>>
Bookmark controller will transition from {375, 667} to {375, 667}  <<Correct but still wrong current size>>
History controller will transition from {667, 375} to {375, 667}   <<Correct>>

2 个答案:

答案 0 :(得分:3)

我尝试使用下面的代码解决此问题。我不确定这是否100%正确,所以如果有人有一个好的解决方案,那么请告诉我们。

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    for viewController in viewControllers! {
        viewController.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    }
}

答案 1 :(得分:0)

没有;坦率地说,我作弊,并使用了以下版本的viewWillTransitionToSize(在真实程序中,这是Apple的AAPLTraitOverrideViewController的子类,让我在iPhone 6上执行双窗格)。

它依赖于当前所选选项卡中的VC具有正确的旧帧大小这一事实,因此当为未选择的选项卡调用viewWillTransitionToSize时,它会查看其兄弟给它的实际大小。然后它应用当前变换并采用绝对值以避免负数。请注意,这仅在VC是标签控制器的直接子节点时才有效。

如果您(或任何人)想出更好的方法,请告诉我们!

- (void)viewWillTransitionToSize:(CGSize)size
       withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
    NSLog(@"%@ will transition from %@ to %@",self.detailItem, NSStringFromCGSize(self.view.frame.size), NSStringFromCGSize(size));
    CGSize realSize = size;
    if (self.tabBarController) {
        //workaround for inaccurate sizes being delivered to non-selected tabs
        NSArray * viewControllers = self.tabBarController.viewControllers;
        NSUInteger myIndex = [viewControllers indexOfObject:self];
        NSUInteger selectedIndex = self.tabBarController.selectedIndex;
        if (selectedIndex != myIndex && myIndex != NSNotFound && selectedIndex != NSNotFound) {
            //not on screen, so use size from selected tab, transformed as indicated by coordinator
            UIViewController * selectedVC = viewControllers[selectedIndex];
            CGSize newSize = CGSizeApplyAffineTransform(selectedVC.view.frame.size, [coordinator targetTransform]);
            realSize = CGSizeMake(fabsf(newSize.width), fabsf(newSize.height));
            NSLog(@"  Instead of: %@, rotating to correct size: %@ ",NSStringFromCGSize(size),NSStringFromCGSize(realSize));
        }
    }
    [super viewWillTransitionToSize:realSize withTransitionCoordinator:coordinator];
}