I am trying to create an action when I turn the screen of my device.
In the Apple documentation I have read that you have to use this method:
override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
println("I rotate.")
self.tabBar.frame = CGRectMake(0, 80, self.view.bounds.size.width, self.view.bounds.size.height);
}
But when I turn the screen in the log does not print "I rotate."
EDIT:
These are the settings of the project:
The willRotateToInterfaceOrientation function is deprecated in iOS 8 as you can see in the Apple documentation here. See the discussion here on StackOverflow.
From the documentation, you also are supposed to call super:
Your implementation of this method must call super at some point during its execution.
That shouldn't cause the issue you are seeing though. Double check that your target allows rotation. Go to your project, select the target, and under general make sure you have other orientations checked. If you have only one orientation checked then you can rotate the device, but it won't change orientation.
Where is this method? It will only be called if in a subclass of UIViewController.
EDIT: It seems that willRotateToInterfaceOrientation is not called in a UITabBarController subclass (which seems to be what you're using) in iOS 8, but it is called in iOS 7. Even though the method is deprecated, it is still called in a direct subclass of UIViewController in iOS 8. But, for iOS 8 and above, it is preferable to use the new viewWillTransitionToSize:withTransitionCoordinator:.
Related
I have an UIViewController that supports all UIInterfaceOrientationMasks
But, in one certain case I need to prevent it from rotation
Before iOS 16 i was just handling this case like this
override var shouldAutorotate: Bool {
return !screenRecorderIsActive
}
And everything was working fine
After update to iOS 16 my controller keeps rotating and I can't find a way to fix it
In my case, I need to prevent auto rotation not based upon a particular orientation, but rather based upon what you're doing in the app and what kind of hardware your device has. And, I need to continue to support iOS versions all the way back to 9.3. These updates forced me to to do the following:
The new functions aren't available back in 9.3, so I have to do some checking if the version of iOS is 16.x. If so, then I had to implement supportedInterfaceOrientations so that the current user interface orientation is queried and only returns TRUE if the orientation requested is the same as the current user interface orientation. In other words, don't allow a change.
Also, since both returning from the background or rotations or events from other view controllers can change my logic choice for which orientations are allowed, I had to be sure to call the setNeedsUpdateOfSupportedInterfaceOrientations method when returning from the background or any other time I needed to prevent auto rotation.
Again, I had to wrap this code in iOS version checks. Finally I had to implement things the old way for older versions of iOS.
I was very disappointed that such a breaking change was introduced. Yes, the methods were deprecated for a long time, but the new methods weren't introduce until 16.0 - and even more critically, my code does different things when using the front landscape camera now available on the iPad 10, so I had to wait until I had a unit in my hands to uncover these issues.
Quoted from the iOS 16 release notes:
[UIViewController shouldAutorotate] has been deprecated is no longer
supported. [UIViewController attemptRotationToDeviceOrientation] has
been deprecated and replaced with [UIViewController
setNeedsUpdateOfSupportedInterfaceOrientations].
Workaround: Apps relying on shouldAutorotate should reflect their
preferences using the view controllers supportedInterfaceOrientations.
If the supported orientations change, use `-[UIViewController
setNeedsUpdateOfSupportedInterface
To implement dynamic supported interface orientations, you can use some code like this:
var screenRecorderIsActive: Bool {
didSet {
setNeedsUpdateOfSupportedInterfaceOrientations()
}
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if screenRecorderIsActive {
return [.landscape] // For example, or a variable representing the orientation when the condition was set
}
return [.all]
}
The multitasking features got updates in iOS 11, one of those was slide over which is demonstrated in the gif below.
With these changes it's no longer possible to use the techniques that check frame size from iOS 9 to detect if another app is a "slide over" over my app.
Is there any new method to detect if another app is running as slide over?
I was able to get this working fairly easily on an iPad Pro (which supports side-by-side apps, not just slide-overs). Here's the code:
class ViewController: UIViewController {
override func viewWillLayoutSubviews() {
isThisAppFullScreen()
}
#discardableResult func isThisAppFullScreen() -> Bool {
let isFullScreen = UIApplication.shared.keyWindow?.frame == UIScreen.main.bounds
print("\(#function) - \(isFullScreen)")
return isFullScreen
}
}
The end result is that it will print "true" if the view is full screen and "false" if it's sharing the screen with another app, and this is run every time anything is shown, hidden, or resized.
The problem then is older devices that only support slide-over. With these, your app is not being resized anymore. Instead, it's just resigning active use and the other app is becoming active.
In this case, all you can do is put logic in the AppDelegate to look for applicationWillResignActive and applicationDidBecomeActive. When you slide-over, you get applicationWillResignActive but not applicationDidEnterBackground.
You could look for this as a possibility, but you cannot distinguish between a slide-over and a look at the Notifications from sliding down from the top of the screen. It's not ideal for that reason, but monitoring application lifecycle is probably the best you can do.
I'm just experiencing something weird and it seems to be a change in iOS 8.
Previously(iOS7) when testing appWillBecomeActive was called before viewDidAppear. Is it so that in iOS 8 it is the other way around? what would then be a good workaround in order to make my app work on both iOS versions? is there some variable to test if viewDidAppear was called so I could run my setup functions of the view again?
EDIT: it actually seems quite random in iOS8. sometimes viewDidAppear is called before appWillBecomeActive. Sometimes it's the other way around...
appWillBecomeActive is a delegate located in your Application Delegate itself.. there's no guarantee that it will be called before any other UIViewController delegates (viewWillAppear,DidLoad,Init)
if you want to make any logic before loading of any other pages come alive.. you may want to use application:didFinishLaunchingWithOptions: and you may want to load the launching view by yourself or create a new delegate to detect that you finished the logic that you'll put in your application:didFinishLaunchingWithOptions: .
I have a unity app, that uses Vuforia AR library. I extended this app with some iOs code. I wanted to be able to display my custom UIViewControllers sometimes instead of the main view controller that Unity uses. But I want to be able to switch back. I.e: I have a button that opens UIViewController with "About app" information and this controller then has "Exit" button to return to Unity controller.
This is my code for adding the new controller instead of the Unity View Controller:
self.unityRootController = self.keyWindow.rootViewController; // keep reference to the Unity Controller
self.keyWindow.rootViewController = controller; // display my own controller
// this pauses the unity and qcar -> so that QCAR doesn't try to recognize objects, when Unity Controller is not up
QCARUnityPlayer::getInstance().QCARPause(true);
UnityPause(true);
Then when returning from my own controller to Unity controller:
self.keyWindow.rootViewController = self.unityRootController; // return to Unity Controller
// start tracking with QCAR and unpause Unity View
QCARUnityPlayer::getInstance().QCARPause(false);
UnityPause(NO);
This works fine except one case, that's caused me to pull my hair ever since encountering it. My app supports changing orientation of screen in both Unity and ObjectiveC code. And this is the trouble: If I open my View Controller while the device is for example in Portrait Orientation, then turn the device to Landscape orientation, my controller gets correctly rotated. But if I at this moment want to close my custom view controller and return to unity controller, the screen gets black suddenly. After rotating the device to portrait orientation, the unity controller suddenly starts working as expected.
I'd like the unity controller to start directly after closing my custom view controller even if the screen orientation is changed. I suppose I have to add some code after I start again the Unity Player here:
QCARUnityPlayer::getInstance().QCARPause(false);
UnityPause(NO);
// TODO: supposedly some code should go here, that fixes black screen
But I tried to find something in the AppController.mm, that is builded by Unity and I could not find anything, that would help me. I found few lines of unity code, that had the word "orientation" in it, but I tried to use that code and didn't help. Does anybody know, what should I do, please? Thanks a bunch :)
Not sure if you have fixed this, Its been a while... But the reason that your UnityViewController is not functioning properly is because a view controller that is not visible will not receive rotation events. Because you are setting your view controller as the root view controller, the UnityDefaultViewController defined in "iPhone_View.mm" is not receiving rotation events.
I have been studying Unity's rotation for a while now as I have my own issue with a similar setup.
There are a few things that you might be able to try:
In iPhone_View.mm there is a function that is defined called: UpdateOrientationFromController(UIViewController* controller) that might be able to solve your problem. You would want to call this function on the view controller that you designed yourself where you placed your //TODO comment. That function calls a few key functions and methods that handle Unity's interface orientations:
ConvertToUnityScreenOrientation: for some reason Unity Uses their own defined screen orientations, this internally converts the orientation to what Unity uses.
QCARUnityPlayer::getInstance().QCARSetOrientation(): QCAR Also needs its orientation to be set
UnitySetScreenOrientation(_curOrientation): The unity library has an internal way of checking the screen orientation at every rendered frame. I think this function sets an internal flag for the Unity View to check in CheckOrientationRequest() defined in iPhone_View.h as well.
AppController_RenderPluginMethodWithArg is called, I am not sure what this does, but I think it does something important
OrientTo(_curOrientation): this kicks off the actual orientation change and handles the right calls. This includes the call to AppController's onForcedOrientation: method that does the final orientation.
You may be able to call AppController's onForcedOrientation: method directly with a UnityScreenOrientation after you convert a UIDeviceOrientation to a UnityScreen Orientation with ConvertToUnityScreenOrientation() defined in iPhone_OrientationSupport.h. You may not want to call this method directly though, because there are quite a few things that are involved with Unity's orientation methods. You would do this when your app returns from presenting your view controller.
The last thing, and the "hackiest thing" that you can do, that will get the job done, but not in the most efficient way, is to add UnityDefaultViewController to your ViewController as a child ViewController with the addChildViewController: UIViewController Docs, or maybe as just a property, and then override the willRotateToInterfaceOrientation:duration: and didRotateFromInterfaceOrientation:in your ViewController and after calling super, pass the message to the UnityDefaultViewController. This will cause the UnityDefaultViewController to update the UnityView every time the orientation changes, even though the view isn't actually visible. You may or may not need to unpause Unity in order for this to function.
Of the three methods, the last one should definitely work, because I have implemented it myself. However, the first one should work as well, because Unity uses it several times to check the devices current orientation from the splash screen.
Hope this helps!
I am working in flash CS5.5 on an app for iOS. I want to get the ipad/iphone to stop animating the orientationChange and just change it directly, is this possible?
I thought this was a solution but it didnt help AS3 - iOS force landscape mode only?.
If you try setting Stage.autoOrients = false;, the flash.events.StageOrientationEvent.ORIENTATION_CHANGE will never fire. That's helpful for disabling orientation changes altogether, but not for your issue. While I haven't tried it myself, you may be able to listen to the event:
flash.events.StageOrientationEvent.ORIENTATION_CHANGING
You may be able to call event.preventDefault() in that listener to stop the actual rotation from occuring. Then you can manually set it yourself:
Stage.setOrientation(StageOrientation.ROTATED_RIGHT);
have you tried the SO answer: Disable orienation change rotation animation ?
the code from that answer that goes in the view-controller that is the home for your flash CS5.5 or air 3.5 is:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[UIView setAnimationsEnabled:YES];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
[UIView setAnimationsEnabled:NO];
return TRUE; /* Your original orientation booleans, in case you prevent one of the orientations */
}
that code makes use of native iOS UIViewController functions that can be overridden. you would have to have a native iOS objective C class that overrides UIViewController, and then you could insert the code above. calls are made when the device is rotated to these as part of view controller life cycle.