didRotateFromInterfaceOrientation在旋转时触发两次

时间:2014-12-14 20:58:05

标签: ios objective-c

我意识到在iOS 8中不推荐使用didRotateFromInterfaceOrientation;但是,我有一个需要与iOS7保持兼容的应用程序。我遇到的问题是,当设备旋转时(在这种情况下为iPad),此方法被调用两次。这发生在实际设备以及模拟器上。我只是在方法中放了一个NSLog来显示它。

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 
{

        NSLog(@"didRotateCalled");
}

我还检查了willRotateToInterfaceOrientation,但是只有一次调用才能正常工作。

为什么didRotateFromInterfaceOrientation方法每次轮换会被触发两次?

快速更新。我提出了一个断点,揭示了一些有趣的东西。此视图为UISplitviewcontroller,看起来该方法首先针对UISplitviewcontroller调用,然后调用UIViewController。不知道为什么......

一些其他信息。我正在使用Storyboard一个用于iPhone和另一个iPad。 iPhone不使用splitViewController。代码库是共享的,因此在prepareForSegue我执行以下操作:

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
            UISplitViewController *splitViewController = (UISplitViewController *)self.view.window.rootViewController;
            splitViewController.delegate = segue.destinationViewController;
}

3 个答案:

答案 0 :(得分:3)

我有答案。我刚刚下载了适用于iOS 7.1的模拟器,以便在最新的Xcode中使用。我发现在iOS 7.1下运行时不会调用viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator方法。但是,我还发现,我在两次旋转触发中描述的问题不会发生在iOS7中的willRotateToInterfaceOrientation方法,但在iOS 8中也是如此。这是Apple的一个明显错误。

看起来我需要检测客户正在运行的操作系统版本,如果是iOS 8或更高版本,我将不会在willRotateToInterfaceOrientation方法中执行任何代码。但是,我可以为iOS 8设备保留viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator方法,因为iOS 7会忽略此方法。

我不知道这对于splitviewcontrollers或iOS 7和8之间使用旋转的所有视图方法是否只是一个问题。如果您的应用程序没有覆盖此方法,那么您将永远不知道。如果它是你将面对我上面做的。不好。

以下是我用来检查版本的代码:

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    if (NSFoundationVersionNumber == NSFoundationVersionNumber_iOS_7_1) // use this only for iOS7 devices as otherwise this fires twice under iOS8
    {
        ...
    }
}

我已离开-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator方法,因为这将被iOS 7设备忽略,但将由iOS 8.x调用,大概在上面。

答案 1 :(得分:1)

我有同样的问题(虽然在我的情况下,willRotate也会在iOS 8上执行两次)。我使用了以下解决方法:

BOOL _willRotate; // iVar for the state

// Methods that should be called from willRotate/didRotate (can be inline)
- (BOOL)workaroundIOS8RotationMethodsCalledTwice_forWillRotate_shouldExecute
{
    if(_willRotate) {
        return NO;
    }
    _willRotate = YES;
    return YES;
}

- (BOOL)workaroundIOS8RotationMethodsCalledTwice_forDidRotate_shouldExecute
{
    if(_willRotate) {
        _willRotate = NO;
        return YES;
    }
    return NO;
}

// Inside willRotate (return if shouldn't execute):
if(![self workaroundIOS8RotationMethodsCalledTwice_forWillRotate_shouldExecute]) {
    return;
}

// Inside didRotate (return if shouldn't execute):
if(![self workaroundIOS8RotationMethodsCalledTwice_forDidRotate_shouldExecute]) {
    return;
}

答案 2 :(得分:0)

我发现viewWillTransition针对不同的UIViewController个实例进行了两次调用。在第一次调用时,self是有效的实例。但在第二次通话时,自我无效。未在此无效实例上调用viewDidLoad()。 我在viewDidLoad添加了一个成员并设置了值,然后检查self是否有效。

class MyViewControler: UIViewController {
  var last_width:CGFloat?

  override func viewDidLoad() {
    super.viewDidLoad()
    print(" viewDidLoad self \(self) has address: \(Unmanaged.passUnretained(self).toOpaque())")
    last_width = self.view.bounds.width
  }

  override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    print(" viewWillTransition self \(self) has address: \(Unmanaged.passUnretained(self).toOpaque())")
    // Bug? viewWillTransition called twice with diffent self instance, ignore second call
    if (last_width == nil || last_width == size.width) {
        return
    }
    last_width = size.width
  }
}