I have an application which can show user-created countdowns.
I have a Today extension widget which shows a few of the user's countdowns and when you tap one, it opens the app and jumps to the view controller for that specific countdown.
I've implemented this via URL scheme. When I tap on a countdown in the widget, it uses the url scheme to open the app. In application(_: open: options:), the app delegate:
Gets the countdown's UUID from the opened URL
Gets the index of the countdown object with that ID in the main view controller's array of countdowns (or returns false if it can't find a countdown with that ID)
Calls dismiss(animated: false) on the main view controller to get rid of any presented view controllers
Calls popToRootViewController(animated: false) on the main view controller's navigation controller
Performs a segue that shows the countdown
This all works great. When I tap a countdown in the widget (or even just type in the URL with a known UUID in Safari) then the app opens up straight to the right countdown.
But it only works if the app was already suspended in the background. If the app isn't open yet, it just opens the app like normal, I guess because the main view controller isn't loaded yet when the app is told to open the URL. How can I get around this? Is there a different or better way I should be implementing this?
Related
I have an Apple TV app that starts out with a splash page. It plays a short video and does some setup networking. After these both finish I automatically transition the user to a Landing page for them to sign up for the service.
let langingPageVC = LandingPageViewController(nibName: nil, bundle: nil)
self.present(langingPageVC, animated: true, completion: {
print("Transferred to landing page")
})
The problem occurs when the user hits the menu button from this point. They are automatically taken back to the splash page, and the app just displays the static image it display while waiting for the networking to complete and stays there. The user can then press the menu button again and exit the app. If the user re-enters the app, they will be on this static image and not be able to do anything.
How can I make it so the app just goes to background directly from my landing page and doesn't go back to the Splash page? I know how to detect the menu press with a gesture recognizer, but there doesn't seem to be a call I can make that will background the application from that point.
I have tried removing the Splash page from its parent in the completion block and that didn't work. I saw something about setting the page as the keyWindow but I got a message in the log saying not to do that and that the system is supposed to handle it, and it also didn't work.
Any help is appreciated.
Two possible options:
Instead of presenting LandingPageViewController from SplashViewController, you could set LandingPageViewController as rootViewController. That way your splash will not be in your backstack of viewcontrollers.
Present SplashViewController in a separate window over LandingPageViewController. Once your video finishes you can dismiss the window.
I recently refactored an app to use a UINavigationController and pushViewController(...) to transition back and forth between the main UIViewControllers of my app. Previously I was using present(...) with no issues. The app is a music player and has the appropriate background mode.
The transition to view controller B from view controller A happens after a 5 second countdown and thus can happen in the background if the user hits their home button or turns the screen off.
The issue is that the push, and all relevant events that are supposed to kick off when the view did appear, do not fire while the app is in the background, and immediately fire as soon as I turn the display back on or bring the app into the foreground.
Is there any way to force the push to happen even if the app isn't visible, or a different method to push and display the view controller?
Thank for any insight!
let nav = self.parent as! UINavigationController
print("Attempting to .pushViewController...")
nav.pushViewController(sessionVC, animated: false)
print("After .pushViewController...")
I have "Tinder" like swipping view that is located in a CardViewController. The card View Controller is accessed by moving through two other view controllers. i.e. Load App -> FirstViewController -> SecondViewController - > CardViewController.
When I am in the Card ViewController and I go into background mode, the app launches on the FirstViewController and on going to the cards, they are loaded from the first card in a stack of about 10?
Is there anyway to load the app from the last Card I had swipped and in the CardViewController without having to navigate from the FirstView Controller again?
I would really appreciate the help as it's horribly affecting some of my users.
An example of a Tinder like card view is shown!
The problem, from the sound of it, is not what happens when the app goes into the background — that would leave it in exactly the same state when it reactivates. The problem is what happens when the app goes into the background and quits. Your app is then relaunched from scratch, which is why you find yourself in the first view controller. What's upsetting you is the difference between the app's behavior in these two situations.
Apple provides a solution to this situation: UIViewController, along with the App Delegate, has methods permitting you to save and restore state. When the app goes into the background, the current configuration (what view controller's view is showing) is saved. That way, even when the app quits, when it relaunches it can get back to that configuration before it appears to the user. Thus, coming back from background-and-quit looks just like coming back from mere backgrounding.
For full details, see Apple's documentation. This is a good place to start:
https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/PreservingandRestoringState.html
I have an app that needs to fetch some remote configuration files before it starts or after it has been idle for some time in the background. I use a loader view controller to do the job while displaying a splash screen with a loading indicator.
What would be the best way to display the loader (assuming I also want to refresh the whole app after idle time in background):
Display as a modal view controller and dismiss when finished
Set the loader as root view controller and set back the original root when the loader finish (this method triggers a dealloc for the original root and creates it from scratch)
Go with option 1. I've used it many times and it works brilliantly. The best thing about using a modal view controller is that you can smoothly transition when you dismiss it, and you can just present it un-animated on applicationDidFinishLaunch so that it's there instantly for the user to see.
Display as a modal view controller and dismiss when finished.
This option will be more feasible when your app will starts from background state. You can show this with no animation show it will feel like splash and you can fetch remote configuration files.
I have my local notification working, but when I click View to come back to the app, in the app delegate I am trying to load a specific view, but it wont take. Is this possible or not? It always just comes back to the last view viewed.
When you tap "View" on the notification, it takes you back to your application, and your application shows whatever it was showing before (if it was backgrounded) or is launched.
If you need to show a particular UI in response to the notification, consider implementing the <UIApplicationDelegate> method -[<UIApplicationDelegate> application:didReceiveLocalNotification:]. In that method you can inspect the notification and transition to the appropriate interface.