I'm not sure if there any potential workaround for this, but here is the steps to reproduce this issue:
Create UIWindow either with AppDelegate or SceneDelegate;
Assign overrideUserInterfaceStyle with .light for UIWindow or change it in Info.plist
Assign UIHostingViewController with SwiftUI view as a rootViewController for UIWindow;
Create any repeatForever animation in SwiftUI view;
Go to background and then foreground.
Actual result: repeatForever stop repeating.
Sample app to reproduce the issue: https://github.com/denandreychuk/overrideUserInterfaceStyle
Related
I've adopted the new iOS 13 modal presentation style across most of the modals in my app, however one navigation controller doesn't really fit the new style well so I set it to
UIModalPresentationFullScreen
when presenting it which works fine.
I just noticed a bug that when my app undergoes state preservation and restoration whilst on a ViewController being presented modally its loaded back in after restoration with a modalPresentationStyle of UIModalPresentationPageSheet.
As built in properties of a ViewController their state restoration is Apple's responsibility and I guess they just missed out handling it properly.
Thankfully I've been able to fix the issue by adding the following to my existing state restoration handling
- (void)decodeRestorableStateWithCoder:(NSCoder *)aDecoder
{
...
self.navigationController.modalPresentationStyle = UIModalPresentationFullScreen;
}
Anyone else encountered this or got an alternative solution?
Cheers
I am having a problem with the new VC presentation styles in iOS 13. I want to implement the new "stack" presentation.
However I do have an issue where the PRESENTING view controller is not shrinking down as it should causing a really ugly look.
The only solution I found to this problem is setting the background (ie presenting) VC as the new root view controller with
window.rootViewController = self
However this is not recommended by Apple and causes lots of odd bugs like dissapearing status bar or cutting of segue animations.
Can someone please explain to me how to fix this issue or how to properly use the new presentation styles or how to properly set a new root VC.
The intended behaviour:
The buggy behaviour:
The rotation animation occurs for the status bar (which has the clock and the battery icon), but the view itself just changes size, it doesn't do the page flip animation. In the gif (below), I did a few screencaptures of the rotation animation in slow motion. You can see the clock and battery icon rotate into the view, even though the content just scales.
http://imgur.com/gallery/Q3OXCIH
I found some similar, but not quite the same posts:
iOS Device Rotation Instant Snap rather than animation
iOS 9 Orientation Auto-Rotation Animation Not Working, But Always on Main Thread
This is somewhat repeatable- at first, the rotation occurs correctly, but after I programmatically change the tab view controller index, it can trigger. After it triggers, the rotation animation does not occur for the view until after I reset the app.
Code where I change the tab view controller and then change it back:
[appDelegate.tabBarController setSelectedIndex:0];
...code to operate on the code at index 0...
[appDelegate.tabBarController setSelectedIndex:2];
To emphasize- it DOES animate the rotation correctly when I first run the app. Behaves the same in simulator and in hardware. IOS9. Xcode 7.1.1.
Anyone know why a viewcontroller's content would stop animating during rotation?
edit-
To answer fragilecat's questions:
1) I am set up to use the rotation functions, as described in https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/#//apple_ref/occ/clm/UIViewController/attemptRotationToDeviceOrientation
I have implemented shouldAutorotateToInterfaceOrientation and shouldAutorotate and supportedInterfaceOrientations. The supportedInterfaceOrientations gets called once, when the viewcontroller loads. shouldAutorotateToInterfaceOrientation and shouldAutorotate are apparently never called.
2) I am receiving size change messages via viewWillTransitionToSize- this is ios9 so there aren't any rotation messages. willTransitionToTraitCollection is apparently never called, though it is overriden. I am calling the super for both.
3) I am not using viewWillLayoutSubviews() or viewDidLayoutSubviews(). I am only overriding viewDidLoad and viewWillAppear. These do not affect rotation.
4) I am not dynamically changing rotation methods.
What I did notice, is that rotation works at first, but then fails (doesn't rotate but just scales), after I change the tabBarViewController selectedViewController programmatically after the use clicks "ok" to an alertview. I haven't figured out why yet, but it is repeatably after that event.
Sequence of the bug:
Works fine, rotates ok.
User hits "ok" to an alertview
I programmatically call [tabBarViewController setSelectedIndex:0]
I call some functions on the viewcontroller at index 0.
I programmatically call [tabBarViewController setSelectedIndex:2] (back to the original)
rotation now does not occur reliably
Anyone know why a viewcontroller's content would stop animating during rotation?
The child view controller's rotation method's are configure incorrectly.
Your child view controller's are not receiving rotation messages.
You have custom code in the view controller's layout methods.
Your code is dynamically altering rotation/layout/animation methods.
I am looking for direction on what kind of bugs can produce this type of error.
This is some what hard to answer with out seeing your code, but here are the steps I would take in trouble shooting this issue.
Confirm that your child view controllers are correctly setup for rotation.
UIViewController Rotation Methods
Confirm that your child view controller's are receiving the following messages so that you can rule out this as the issue as this is how rotation is handled in iOS 9.
func willTransitionToTraitCollection(_ newCollection: UITraitCollection,
withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
func viewWillTransitionToSize(_ size: CGSize,
withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
If you are overriding these methods else where you should make sure you call the super's version, see UIContentContainer for details.
Comment out any custom code that you might have in viewWillLayoutSubviews() implementation of your view controllers. Also you can check your frames between viewWillLayoutSubviews() and viewDidLayoutSubviews().
EDIT
You need to execute the tab change on the main thread. If I am correct you are using the delegate of UIAlertView? I don't think your on the main thread went you make your call!
dispatch_async(dispatch_get_main_queue(), ^{
[appDelegate.tabBarController setSelectedIndex:0];
});
I've been working to implement a custom modal transition that uses a UIPresentationController subclass to create and manipulate an additional view during the presentation and dismissal. Apple helpfully provides an example of how to do this in the documentation, but I've hit a snag.
When presenting the modal, my custom view animations work perfectly, but when I dismiss the modal, the animations applied to the custom views in dismissalTransitionWillBegin play out of sync with the animations specified by the transition animator object I'm returning from animationControllerForDismissedController:. Specifically, the custom view's animations are ignoring the duration of the transition animation and are always playing very quickly (the duration appears to be around 0.2 seconds).
What could cause animateAlongsideTransition:completion: to ignore the duration of the base animation?
The source of the trouble appears to be a bug in iOS.
No matter how I refactored or simplified my animation code, I always ended up with the same result, so I started to wonder if there might be something in the way my project was set up that was causing the problem. I dropped my custom modal transition code into a clean project and, lo and behold, it worked perfectly on the first try.
Bit by bit I customized my test app to more closely match my real app and I was eventually able to get the problem to reappear. Through trial and error I found the combination of factors that was triggering the problem:
The presenting view controller is within a UINavigationController
The presenting view controller's bar button items include an image-based UIBarButtonItem
The window has a tint color set
When those three conditions are met, the animation block of the animateAlongsideTransition: call in dismissalTransitionWillBegin will be performed before the animation block of the animateWithDuration: call in animateTransition. This seems to prevent the custom view's animations from getting the transition animation's duration. In my testing, the animateAlongsideTransition: animations ran with a duration of 0.215 seconds, which I believe is the default duration.
I have been unable to find any way prevent the issue from occurring other than removing one of the three factors triggering it. The workaround I ultimately settled on was removing the window's tint color and instead setting a global tint color using UIView's appearance proxy. There are some side-effects--like UIAlertViews' buttons getting tinted--, but for my purposes this was an acceptable trade-off.
I've updated my custom alert class (which is a UIWindow subclass) in iOS8 to set its rootViewController to the UIViewController it is being presented on. This enables the app to automatically rotate my custom alert instead of having to do it manually.
It works well but I'm finding one situation where it doesn't rotate: when I'm on the UIViewController that appears when the app is first launched (which also happens to be the rootViewController of my app delegates window property).
Is this because UIViewController can't be the rootViewController of two UIWindows or is it a bug? Does anyone have a work around for this? It works perfectly on every other UIViewController that I display an alert.