DidRotateFromInterfaceOrientation fires twice during rotation

I understand that didRotateFromInterfaceOrientation deprecated in iOS 8; however, I have an application that should remain compatible with iOS7. The problem I am facing is that when you rotate the device (iPad in this case) this method is called twice. This happens both on the device itself and on the simulator. I just put NSLog in a method to show this.

 -(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { NSLog(@"didRotateCalled"); } 

I also checked willRotateToInterfaceOrientation , but that one works correctly only after receiving the call once.

Any thoughts why the didRotateFromInterfaceOrientation method will run twice per rotation?

Like a quick update. I set a breakpoint at which something interesting was discovered. This is a view of the UISplitviewcontroller , and it looks like the method is called first for the UISplitviewcontroller , and then as the UIViewController . Do not know why ...

Additional Information. I use Storiesboards one for the iPhone and another for the iPad. IPhone does not use splitViewController . The code base is split, so in prepareForSegue I do the following:

 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { UISplitViewController *splitViewController = (UISplitViewController *)self.view.window.rootViewController; splitViewController.delegate = segue.destinationViewController; } 
+5
source share
3 answers

I have my answer. I just downloaded simulators for iOS 7.1 for use in the latest Xcode. I found that the method viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator NOT called when running on iOS 7.1. However, I also found that the problem that I described with double rotation twice does NOT happen with the willRotateToInterfaceOrientation method in iOS7, but again it works in iOS 8. This is a clear bug in Apple.

It looks like I will need to determine the version of the OS on which the client is running, and if it's iOS 8 or higher, I will not run any code in the willRotateToInterfaceOrientation method. However, I can leave the viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator method there for iOS 8 devices, since this method will simply be ignored by iOS 7.

I do not know if this is just a problem for splitviewcontrollers or for all viewing methods using rotation between iOS 7 and 8. If your application does not cancel this method, than you will never know. If this is what you encounter with what I did above. Not good.

Here is the code I use to check the version:

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

I left the method -(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator , as this will just be ignored by iOS 7 devices, but iOS 8.x and supposedly higher will be called.

+3
source

I have the same problem (although in my case willRotate runs twice on iOS 8). I used the following workaround:

 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; } 
+1
source

I found that viewWillTransition refers to different instances of the UIViewController . On the first call, self is a valid instance. But on the second call, self is not valid. viewDidLoad() does not call this invalid instance. I add an element and set the value to viewDidLoad , and then checks to see if it is valid or not.

 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 } } 
0
source

Source: https://habr.com/ru/post/1209026/


All Articles