I am getting a data packet from push notification in my app delegate. If I get this push, I want to segue to appropriate view controller which is a a few VCs deep in my nav stack. It looks really choppy watching the app quickly segue 4 or 5 times to get to appropriate VC.
It looks like I want to create a new UIWindow to cover up my main window while this choppy transition happens. How can I do this with a new UIWindow (have it appear when we know a push is coming through and remove when we reach correct view controller)? Is there another better way to do this?
Thanks a lot!!
If you want to use another UIWindow to initiate this nav stack transition, all you'd have to do is in your application's keyWindow, show some kind of "progress" indication while the transitions are happening in a background window, and then all you'd have to do is set the keyWindow property on your AppDelegate. You can also transition this "setting" with whatever animation you'd like!
Related
I have a strange problem with state restoration for a Universal app with Split View Controller.
The strange thing that I am doing things in a very standard way using a Storyboard and segues and with a restoration identifier for alle relevant view controllers. There is not really any code, as the logic is in the Storyboard and a minimal XCode project shows this.
The problem is with a settings screen that is shown modally as a form sheet presented from the split view controller. My view controller hierarchy ends up correct, but the transition doesn't really make sense. For some reason state restoration animates the modal controller into place.
Since the screen starts out with a screenshot from the last time the app was running, with the settings controller already present, the animation is just visual noise.
I have tried to disable animation on the segue which is respected when entering the settings interactively, but when state restoration does the same thing, the animation is there.
What is the standard way to avoid this?
Calling self.window?.makeKeyAndVisible() in application(_:willFinishLaunchingWithOptions:) solved the issue for me.
More info in the docs:
Important
If your app relies on the state restoration machinery to restore its
view controllers, always show your app’s window from this method. Do
not show the window in your app’s
application:didFinishLaunchingWithOptions: method. Calling the
window’s makeKeyAndVisible method does not make the window visible
right away anyway. UIKit waits until your app’s
application:didFinishLaunchingWithOptions: method finishes before
making the window visible on the screen.
I'm working with some pre-existing code and frankly I'm a bit lost.
My goal is to create a view that displays on the bottom half of the screen when the user RETURNS to the app. This view forces the user to re-enter their password as verification. I've been informed AppDelegate's applicationDidBecomeActive is a good place to handle this process. The issue I'm running into is that the top half of the screen needs to show the view the user was previously viewing before the application became inactive. What is the best way to do this?
What I've been trying to do:
I made a view controller called passwordVerificationViewController and made a corresponding XIB. In applicationDidBecomeActive I try:
UIViewController *myCurrentController = (UIViewController *)navigationController.visibleViewController;
verifyPasswordViewController = [[VerifyPasswordViewController alloc]
initWithNibName:#"VerifyPasswordViewController" bundle:nil];
[myCurrentController.view addSubview:verifyPasswordViewController.view];
This doesn't work. The reason it doesn't work is because navigationController.visibleViewController is not returning the viewController that is on the screen, as I intended it to. I've also tried navigationController.topViewController but it gives me the same results.
Also of note, all of the view controllers in the app are opened via presentViewController and are presented by a navigation controller. I have tried using the navigationController.presentedViewController property but this always returns null.
Would the way I'm doing it work if I could figure out how to get the correct reference to the current on screen view? Is there a better way I can accomplish my goal?
EDIT: Solved using Helge Becker's method. Perhaps not the cleanest way, but I set up the notification center like he suggested. Then I wrapped my notificationHandler in an if statement with the condition, (self.isViewLoaded && self.view.window) as a means to see if the view controller is visible on the screen.
Post a notification in the app delegate methods.
Let the viewcontrollers then register for the notification.
That will allow all viewcontroller respnd to any qpp condition change.
Usualy became active and will enter background are suffice.
I have a board game app that I'm programming which involves a player asking the same question to the other players in a clockwise direction. Since the question is the same for all players, after one player answers the question I want another instance of the same view controller (and its views) to be presented again (with some minor changes in the views to reflect the fact that a different player is being asked the same question).
So here's the problem: When I programmatically try to push the new view controller of type "PlayerAnswerToSuggestionVC" from the first instance of "PlayerAnswerToSuggestionVC" view controller with the following code, there is no animation:
PlayerAnswerToSuggestionVC *patsvc=[self.storyboard instantiateViewControllerWithIdentifier:#"PlayerAnswerVC"];
[self.navigationController pushViewController:patsvc animated:YES];
The new view controller does appear but there is no animation of the transition despite the fact that I am declaring that I do want animation in the "pushViewController:animated:" method. Same thing happens when I try to use a storyboard segue from a UIButton of the first view controller to instantiate a view controller of the same type. The new view controller appears, but without any push transition animation.
I realize that this may be an intended feature and that oftentimes one may not want an animation when going from one view controller to another of the same type. But in my case I do want a visual push transition in order to reflect the fact that the game question is now being directed at a different player. Any ideas on a simple way to implement an animated push transition from an instance of one view controller to another view controller of the same type?
*Additional info discovered: After playing around with the app some more, I have to amend some of my comments above. It appears that the push transition doesn't animate but later in the game the same push transition in another instance of the same view controller class DOES animate. I still have no idea why the push transition doesn't animate the first time time it is attempted, though. Still looking for a pattern to try to understand what is going on...
I've got a UIViewController with two button, prev and next. When I push these button I re-instantiate the same viewcontroller passing it some variables and then I push it on the UINavigationController with no animation.
With this method my memory is always full cause, as far as i know, it is released only when I pop my viewcontrollers.
So my question is.. how could I implement this behavior? I need to free the memory when I load next (or prev) view controller
Build a custom Navigation controller and animate the transitions yourself.
Simplified question: Is there any way to restart the navigationController of an application?. I'm trying to force the application to get his initial appearance.
Long explanation
I've a pet project in iOS and I have a weird problem with the interface that I'd like to solve. I'd like to understand also the mechanics behind this behavior.
I've a simple welcome view, wich shows the splash screen of the application. After that, thread goes to sleep state for 1.5 seconds.
[NSThread sleepForTimeInterval: 1.5];
Then, I'm showing an advertisement view:
AdController *ad = [[AdController alloc] initWithNibName:nil bundle:nil];
[self.navigationController presentModalViewController: ad animated:YES];
[ad release];
And that's all the logic behind. After that, other controllers are pushed without incidence. I want to achieve that, if at any moment the user makes the application go to background (pushing the iPhone/iPad button) then all the controllers must disappear from the stack via pop. In order to get it I'm using applicationDidBecomeActive event from the delegate. The code is the following:
[self.navigationController dismissModalViewControllerAnimated:NO];
[self.navigationController popToRootViewControllerAnimated:YES];
This is driving to some weird visual behaviours. Depending of the moment that the user choose to push de button the transition to the first view is visible. In other cases the ad view is still present, so it is dismissed and then appears the splash screen.
It will be great if there is some way to reset this first controller (splash screen), in order to get all the transitions working as the first time. I've thought about pop it from the navigation controller and the reload another one, allocating again, but it seems a bit complicated.
Is there any simple way to achieve that?
Important Edit: If the user forces repeatedly the application to go background then these exceptions are thrown:
nested pop animation can result in corrupted navigation bar
Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
The easiest way that I've found is to add to the plist file a new row with key "Application does not run in background" and with value YES.
Forces the application to be completely closed and unloaded from memory when the user pushes the button.