Go forward in UINavigationController - ios

I have 2 views, A and B. A is a tableview, and B is a detail view. When a cell is tapped in view A, the appropriate data is loaded in view B and I use [self.navigationcontroller pushviewcontroller] to present it. This all works fine, but if the user presses row 10, lets view B load, goes back, and presses row 10 again, I would like for it to just go forward to the view B that is already loaded. The navigationcontroller always lists as only having one view in the stack. Do I have to manually save a view to the navigationcontroller to re-present? The project uses ARC and Storyboard if that makes a differance. Thanks

For this actually you dont even have to concern yourself with navigationcontroller. Have a UIViewController variable (lets say lastViewController) in your ViewController1 where viewA and viewB reside.
Before pushing ViewController2 the detailed view store that reference in lastViewController. When you pop back and press another row, check if its that same viewController and show the same viewController.
But I would advise against this approach. Keep it simple, let ViewControllerB load again. There could be a scenario where loading again is preferential as it might show the user more latest information row10.

The behavior you are seeing is correct! When ViewController B is needed it is created and pushed onto the stack of the navigation controller and we see view B. When the user goes back to ViewController A and we see view A, ViewController B is no longer needed, and it and its view go out of existence.
This is efficient and lightweight and makes perfect sense. Once you are back in ViewController A and view A, who knows what row the user will tap now? If the user taps row 10 and goes back to A, taps row 10 and goes back to A, over and over, a new ViewController B will be created and go out of existence each time. So what? From the user's point of view it is perfectly consistent; it looks like the same view B! That is all that matters. You don't want to go back to the same view B; you want to create view B all over again. And that is what you do.
Indeed, this is the genius of iOS. With a single tiny screen, it is able to make views come and go without burdening memory and other resources.
For more about UINavigationController architecture, which is what you're using here (master-detail), see my book: http://www.apeth.com/iOSBook/ch19.html#_navigation_controllers

Related

Going from two View Controllers to the same View controller, but when pressing back it takes them to the initial View controller that they were in

I am new to Xcode and Swift 4 so please explain to me like a beginner.
I am developing an app that will help students build engineering experiments. Within the app there are some task that will get them points.The teacher after each task is supposed to go to a 'Score' ViewController and add points to the team with the correct answers. What i am trying to do is, that at the view controllers in which the teacher has to add score, a button appears and takes her to the 'Score' ViewController. But when she presses back, that takes her to the InitialViewController from which she clicked the button.
What i am trying to say is that:
If i have storyboard A B C D ,and A and C have that score button that takes them to the same Storyboard S, when clicking back they go back to the ViewController they were initially in.
Hope i explained my issue well...
EDIT:
diagram of what i want
Hope this helps to clarify, i want the same back button to go to different ViewControllers, depending on which ViewController i was on when i clicked the score button.
For this, you need to use the unwindSegue function in your initial view controller and connect the A and C view controllers to it.

Data passed through segue lost after hitting back button

I have two view controllers A and B and a segue from A to B (type: show) through a next button and a segue from B to A (type: show) through back button. I am passing some data through segue A to B. Data is displayed correctly if I just tap next from controller A and go to controller B.
However, If I tap next and go to controller B and hit back and come back to A and then hit next again, it doesn't work. Any ideas whats going on here? Sorry for the confusing language.
Sounds like your "B to A" is wrong, you're using a navigation stack so you should only push (show) when you are moving forwards. When going backwards you should pop off the top (dismiss)
If you keep pushing, the app will continue to just put more and more ViewControllers in memory, which is bad.
I suspect whats happening here is View A initially has the data and passes it to View B. Then when you press your back button it creates a new copy of View A which doesn't have the data and shows that instead of the original View A.
In Short: (A to B :type - show) (B to A :dismiss the current ViewController)
I agree with user2877496 in that you should not use a regular segue to go back from B to A as you will be adding "A" onto the stack each time.
I just wished to add that one method to dismiss B and go back to A is by using an Unwind Segue.
The Apple documentation covers this quite well
https://developer.apple.com/library/content/technotes/tn2298/_index.html
Did you resolve this? My guess is you put stuff to execute in viewDidLoad (which only runs once at the start of your app) and it needs to be in viewWillAppear so it is called each time you return to your main view controller. Please provide your code for those methods if you require further help.

How can I show a banner UIView as part of the UINavigationController, when in some VC's vs others

Let's say we have a CustomNavigationController that subclass UINavigationController.
Let's use the following example to explain the question.
CustomNavC -> pushes on VC A. From VC A you can push on 2 different VC's. VC B and VC C. We'll say both these VC's push on various other VC's, further down the rabbit hole.
Now, let's say we want to show a UIView that acts as a banner view appearing directly underneath the navigation controller. However, we only want the banner to show on say VC A, VC C, VC E, VC J, etc.
Is there any possible way to do this from the CustomNavC itself? Or is the only way to gain this control of which VC's show the banner... is to put it on the VC's itself?
1) We put it on the CustomNavC view. When the user moves from a VC to a VC that both show the banner (A->C), we want to same banner to remain. We gain this by laying out the banner on the CustomNavC. However, how can we check whether a VC should be displaying the banner or not? Every time the NavC pushes or pops a VC, we would have to check. Likely some function on each VC like -(BOOL)allowBannerViewDisplay and VC's can opt in.
2) If we put the BannerView on individual VC's, it becomes a bit easier but the deal breaker is that if we move from VC A -> VC C, the user is going to see 2 separate banners during the transition instead of the same banner.
So, we need to solve it way 1. The CustomNavC listens for a notification and displays the banner. It would then need to check the currently displaying VC and only display the banner if the VC allowed it. However, if the user transitions to another VC, it needs to recheck the logic of whether the banner is currently displaying and if it is, check if that VC wants it to display.
All of this feels weird to me.
Suggestions?
I've never implemented something like this, but off the bat my thought is this:
Set up this custom view as a new class, and pass the reference along your VCs. Set up a method on the custom View as a class method that takes in a UIViewController and returns a bool for whether or not it should be displayed (rather than on each of your VCs). This class method can get the class and see if it exists in an array of class names or something.
Now, I've never moved a UIView from one VC to another, but I think it's possible to remove the UIView as a subview from the VC it's on, and place it on the new one as a subview.
Alternatively, perhaps you could have a datasource/delegate object for this custom view, and create a new custom UIView on each VC as needed that all reference the same datasource / delegate to set up the state appropriately.

ViewWillAppear & ViewDidAppear firing when dismissing ViewController

I am making an iOS app where I want to present a flow of pages like this:
Basically I want to achieve is to have this flow of pages:
PageA
PageB
PageC
PageD, dismiss back to:
PageC
PageD
PageE, dismiss back to:
PageA (starting point, start over again)
I am using ShowViewcontroller to present the pages (modal) and DismissViewcontroller to dismiss.
As per Apple's documentation if I dismiss a VC early in the stack all subsequent UIViewCOntroller are dismissed too (Apple doc).
However I experience that ViewWillAppear and ViewDidAppear are fired on the UIViewController that are dismissed even when they do not appear (e.g. in the example when dismissing back to PageA from PageE then ViewWillAppear is called on PageD, PageC, PageB too).
This does not seem logical to me. Can anyone explain why this is happening? And perhaps correct me if I am approaching this the wrong way.
I am using Xamarin.iOS.
Apple doc:
If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.
The ViewControllers work with a stack. Whenever a new ViewController (of any type) is added to the stack, You lose more and more control of your ViewControllers (especially when using a modal for your ViewControllers). So, say you have 5 ViewControllers in your stack (A, B, C, D, E, as per your example), and assume they are created in the order as stated, in order to return from ViewController E to ViewController A, you'd have to go through the entire stack. That means that every ViewController in your way needs to be displayed first, in order to dismiss is (since you already have ViewController E displayed, this doesn't occur here).
I hope this helps you. Good luck!
Love and regards,
Björn

iOS ViewControllers Flow

Now, I have a table view called Products with a add button on the navigation bar. When click on add button, the new view controller will be pushed to show which called AddItem. Here is the thing, Can I open a new view controllers A from AddItem and reopen Products from A?
May be my description a little bit confused.
ProductsTableViewController --(Push)--> AddItemViewController --(Modal/Push)--> AViewController --(Modal)--> ProductsTableViewController(Should be exact same as the first one)
And there may be some controllers between AddItemViewController and AViewController.
I have two solution:
1. When open ProductsTableViewController from A, get the same instance as before
2. Create a new instance of ProductsTableViewController and get data from an singleton class.
My concern is that is there any memory leak or protential risk?
your best bet is to use delegates. not sure why you want to do this, but if you have all your vcs in the stack, and your "ProductsTableViewController" is the root, then just have it move to the top of the stack.

Resources