Push segue from a view controller to itself doesn't animate - ios

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...

Related

Swift IOS keep view controller running in background after pop

My app consists of two views. The first one is a GMSMapView and the second one is used to connect to a Bluetooth device that sends coordinates.
After the Bluetooth device is connected, I use a delegate to send the information back to the map view and move a marker around. To transition between views I was previously using segues, this didn't stop the Bluetooth view controller and the data made its way like I wished to the map view.
I ran into the problem of my map view being reinitiated so I decided to use a navigation controller. Now I use a push segue to get to my second view, and pop to come back to the same instance of the first one. Great, that worked! The issue I have now is that popping the second view seems to stop it completely from running in the background like it used to. Is there a way to keep it running in the background like it did before?
What I'm currently using to pop the second view is
self.navigationController?.popViewControllerAnimated(true)
Any idea would be appreciated! Thanks!
A popped view controller does not "stop running". It is returned to you, and if you don't retain it, it is completely destroyed.
If you don't want that to happen, retain it when it is returned. You are currently ignoring the returned view controller:
self.navigationController?.popViewControllerAnimated(true)
Instead, keep a reference to it:
self.mySecondViewController =
self.navigationController?.popViewControllerAnimated(true)
Be warned, however, that this is a very unusual architecture. You will not be able to use the storyboard segue to push again, because it will push a different copy. It would be better to abandon your navigation controller architecture entirely, as it is completely unsuited to the idea of a view controller persisting after it is popped. If you want an architecture where two view controllers persist simultaneously, you would be better off using a UITabBarController — or, even better, reorganize your app completely. The notion that you need the view controller to persist after being popped is a "bad smell": it means that you have put the functionality in the wrong place. Put the functionality in a place that does persist, rather than forcing the view controller to persist in some artificial way.

Observer for monitoring when view controllers' viewDidAppear have been executed

Summary of question
UINavigationControllerDelegate:didShowViewContoller makes it possible to get notified whenever any view controller has been displayed (as opposed to being loaded), provided its within the context of a navigation stack.
I want to know if such observation is possible for all view controllers if there isn't a navigation stack.
More background
I have an app where view controllers can suddenly appear based upon timers and local notifications firing, thus their appearance is effectively random.
If one VC triggers and gets displayed at the same time as another was in the process of getting displayed then there can be an issue (if you're experienced with iOS you'll be aware if one VC pushes another from within its viewDidLoad, rather than its viewDidAppear you will get an "attempting to present X on Y whose view is not in the window hierarchy" error)
How I solve this is I have a list of VCs to display and they get displayed by a view controller co-ordinator which implements UINavigationControllerDelegate's didShowViewContoller and doesn't display the new VC until didShowViewController has been invoked.
This works perfectly.
But now my problem is I want to do a similar thing for an app that isn't using a navigation controller, and thus I can't use UINavigationControllerDelegate:didShowViewController to observe globally when a view controller has been displayed. Does anybody know of another elegant mechanism for doing so?

Showing master view on some pages and preventing the user from hiding it

I have an iPad app with a UISplitviewController set as the root view controller of UIWindow. The master view controller (i.e. the view controller of the left view) is the UISplitViewController's delegate with the delegate method shouldHideViewController returns YES, this means when the app first launches the left view will be hidden and can be shown (and hidden) by the user gesture, i want to show the master view when i navigate to detail pages and prevent the user from hiding it using the gesture, i've tried to call shouldHideViewController method on the delegate to let it returns NO the second time it got called but this time it has no effect, the master view keeps hidden in detail pages and can be shown with the user gesture.
any ideas to achieve showing of the master view with this scenario would be highly appreciated.
This may only be a partial answer because I'm not sure what you mean that you call shouldHideViewController method on the delegate. My understanding is that only the UISplitView should call this method. If you call it, then it will not effect the UISplitView, because it wasn't what made the call. In other words, the delegate method is used by UISplitView to get some information (and allow you a place to do additional things to other stuff) but it is not used as a way to tell the UISplitView what to perform.
Having said that, at least for the gesture activation/deactivation, I would think that in splitViewController:shouldHideViewController:inOrientation: you could do something like
[svc setPresentsWithGesture:NO];
I don't see any way to programmatically tell the UISplitViewController to display or hide the master view controller because the delegate only tells it if it should proceed in presenting or hiding the master when it is going to try and do that. It does seem like there should be a way to do this though.

Design patterns for handling UILocalNotifications (how to know where user is within branching app)

I have an app which uses UILocalNotifications (though the question would also be relevant to PushNotifications). When the user receives a local notification, depending on the state of the app and the choice they make in the notification alert, I want to present a specific viewController. The issue is they may currently be in a "pushed" viewController through a segue or in a modal ViewController and I am not currently tracking where the user is within the possible branches.
I am wondering if there is any sort of design pattern or standard way of handling a mixed presentation mode app like this? Particularly if there is any built-in way to determine which is/are the active ViewController(s) without my having to setup a breadcrumb system. This would matter, for example, if the user is already viewing the viewController to be called as a result of the localNotification.
I realize my need/explanation is a little muddled. I'll edit and update this if anyone needs more info.
OK - I think I have a solution through the Apple docs View Controller Programming Guide for iOS: Presenting View Controllers from Other View Controllers
Each view controller in a chain of presented view controllers has
pointers to the other objects surrounding it in the chain. In other
words, a presented view controller that presents another view
controller has valid objects in both its presentingViewController and
presentingViewController properties. You can use these relationships
to trace through the chain of view controllers as needed. For example,
if the user cancels the current operation, you can remove all objects
in the chain by dismissing the first presented view controller. In
other words, dismissing a view controller dismisses not only that view
controller but also any view controllers it presented.
So I can cancel any chain of modal viewControllers by dismissing the first modal viewController in the chain.
I can determine if there is currently a modal viewController being presented using:
self.window.rootViewController.presentedViewController
If the property is null then there no modal viewController is currently being presented. And for completeness (hackishness..) I can test is the presentedViewController has a presentedViewController, etc.:
self.window.rootViewController.presentedViewController.presentedViewController

iOS - pushViewController vs presentModalViewController difference

What is the difference beetween calling presentModalViewController and pushViewController, when :
animation is set to NO (even if yes, that's just an animation style that can be changed).
a navigation controller is defined when presenting the modal view, so it can be navigable too, with a call stack, ....
Is this just to be able to go back from the first pushed view ? Woooaaaaaa.....
I guess the difference is elsewhere and deeper. No ?
Ignoring transitions/animations and how things are structured behind the scenes (which aleph_null's alswer provides a good discussion of), the only user-facing difference is the ability to return to the preceding view automatically using the navigation bar.
If you use pushViewController you will automatically get a "Back" button in the navigation bar. If you use presentModalViewController you do not, and generally will have to implement your own controls and/or callbacks to handle dismissing the controller.
Conceptually the modal presentation style is generally used for atomic tasks that you cannot navigate away from (i.e. you either complete the task, or you cancel, and you cannot do anything else within the app until you do one or the other).
If you're wondering why have the difference in the first place, I can't say. Personally I think frameworks that provide a unified API for moving from one controller to another (like cocos2d, or Android) make a lot more sense.
The most important difference is about semantics. Modal view controllers typically indicate that the user has to provide some information or do something. This link explains it more in depth: http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ModalViewControllers/ModalViewControllers.html
Here's another, less abstract difference they talk about:
"When you present a modal view controller, the system creates a parent-child relationship between the view controller that did the presenting and the view controller that was presented. Specifically, the view controller that did the presenting updates its modalViewController property to point to its presented (child) view controller. Similarly, the presented view controller updates its parentViewController property to point back to the view controller that presented it."
Also see this thread: why "present modal view controller"?
Take a look into the viewControllers in the image
The top 2 viewControllers(login & submit) at the top left are disconnected from the tabBarController & NavigationController
The rest of the viewControllers are embedded in a NavigationController. They somehow belong to the natural flow of the app.
Now you have to ask yourself
Do I need to always show login + submit page every time? It would be pain in the neck for the user to each time go to login even if they logged in last time. These 2 screen really don't fit the natural flow of the screens. So what do we do? We just add them modally using presentViewController
However for the rest of the viewControllers we want to keep them inside 2 navigation so we can easily go back and forth so we use pushViewController
For more information I recommend you to see this video
The image was also picked from this great answer. It's worthy of a look.
This is what my experience says,if you want to manage a hierarchy of views,better go for pushViewController in the navigation controller. It works like a stack of view-controllers in the navigation controller. If however the requirement is just to show a view on executing some actions on the parent view controller then the best way is presenting it modally.
If you need a complex push pop logic always prefer a pushViewController.
UINavigationController are used when you want to have some sort of hierarchal representation of your data (ie drill down). They work using a stack of UIViewController subclasses. Every time you “drill down”, you simply add another view controller to the stack. Then, the “back” logic is simply a matter of popping view controllers off of a stack.
You can check out this link:
http://www.icodeblog.com/2011/10/11/back-to-basics-an-introduction-to-view-controllers/

Resources