I am currently working on an Xamarin iOS application that has some navigation issues.
What i am currently trying to achieve is to push a ViewController while at the same time popping the previous one off. The reason for this is that I have one ViewController that shows some specific questions from this view controller i can spin up another ViewController of the same type and the user can fill in some more questions. What i want to be able to do is pop the previous filled in view controller so when the user hits the back navigation it takes me back to my home view controller (and not through all the previous instances of the question controller).
I also can't use the PopToRoot or PopToViewController.
I have tried doing a pop without animation and a push with animation and results in a quick flicker of the underneath viewController which is colourful so its a bit of a shock to the eyes.
The other thing I have tried is to manipulate the navigation stack underneath by pushing on the questionController and then removing from the stack the old viewController the problem with that is i have some tear down on the ViewDidDisappear (i work out if its a pop disappear rather than just a cover up) which doesnt seem to be called because of the manual removal. So along this method is it ok to call the ViewDidDisappear to carry out my unwiring so there is no leaks?
Many Thanks for your time reading.
Related
So, I have a tab bar view controller, however at some point I need to manually segue to a viewcontroller that is not attached to the tab-view controller. The segue works, but then it jumps back again to the previous view controller randomly after 1/2 a second to 3 seconds, not all the time, but often. Occasionally I see a message saying something along the lines of "cannot dismiss viewcontroller while another dismiss or presentation is already taking place" but I've double checked all my code and there are only three places that make the jump, none of which can be called simultaneously. What I need to know then, is how I go about dismissing the tab viewcontroller in the view did load method of the modaled to controller. Swift explanations are no good to me thanks. Also, not related to this question persay, but can anyone tell me what the sliding bar thing that looks like a UISlider and tracks the progress of a song is called?
I cannot find the answer to this although I have implemented this rather a few times already, but maybe the wrong way.
Say I have an App for iOS, it has a main screen, which goes to a list, that list has a < back (to main) and an add button. Now when I click < back, I go back to main as that's the pop() from the stack. No issues so far.
Now when I click the add button, that is added to the stack as well; when I click back on that screen I go back to the list which is fine.
The problem is; when I save the new item, I want to go to the detail screen, but I don't actually want to have the add screen on the stack anymore while it will be there. I want the < back button for the detail item pointing to the list.
I know how to do this, but what is actually the best to implement this with the navigation stack?
Well for adding elements the best practice is to present an ModalViewController.
In this way it is not added to the stack.
Update
Let's take as examples simple apps that apple provide with iOS, Contacts app. When you want to add a new contact a VC is presented.
You'll need to implement "Done" or "Save" button that will dismiss the modalViewController and if you want to take the user into detail screen you could post a notification or other mechanism on dismissViewController method's completion block that will push the detail page from the list. But be careful on animations if you dismiss the modal VC animated and push the detail page animated you could get some unexpected behaviour. My proposal is to dismiss the Modal VC animated and push the detail page without animation.
You can override UINavigationController's viewControllers property after you pushed detail view controller. Just get current viewControllers property array, iterate and find the one you don't want to see and remove it. Remember to set viewControllers array again.
https://developer.apple.com/library/ios/documentation/Uikit/reference/UINavigationController_Class/index.html#//apple_ref/occ/instp/UINavigationController/viewControllers
In my application i'm using the navigation controller as an "Action Bar" and in most scenarios there is no Back Icon.
If i understand correctly, when i'm using segues to move to the next screen, iOS keep a reference of my last screen so i will be able to press back and return to it quickly.
can i have the same segue with moving to next screen, but somehow tell the navigation bar not to save an instance of the the last view controller ? i need that in order to avoid duplicate view controllers in the view controllers stack, and to avoid overloading the memory.
I have a complex flow between view controllers (vc). When my main view controller shows, it checks if a user is logged in, and if not, it pushes a log in vc in viewWillAppear. The login then can the push a register vc. Further, on app's very first start, it also shows a special vc, also from the main vc's viewWillAppear (just once). It does not matter if the user has logged in or skipped the log in.
The app can be opened also by custom URLs, which should open one of my vcs. The app must start/resume at that screen without any visble transition between vcs. All this flow is handled from my main vc, which handles this in viewWillAppear and in didBecomeActive which is an observer for app's UIApplicationDidBecomeActiveNotification. Some of those custom URLs must open the login screen first.
My naive approach was to handle all this logic in my main vc's viewWillAppear where I pushed vcs base on the current state. This works for pushing the login screen on app's start without any problem. The problem is that when I return from the login and I need to push another vc. The main navigation controller knows that something was pushed (the back button becomes visible) but the old vc is visible (the main), with partially broken views, and does not react to touch events. Tapping the back button makes a complete mess from my app.
I googled and the problem seems to be that we cannot push a vc while another one is popping. I have found a BufferedNavigationController, which solves this, but it does not work correctly under iOS7 yet. I do not even see any logs in device's console.
Another issues is that while the app is in the background a memory warning could mess my vc's and the app has completely different startup than a normal resume from the background.
At the moment I came with a quick hack where I create a custom backstack for all the situations and set it as the navigation controller's back stack and push the last vc on top of that stack. Then in the login/register screens I modify the backstack if a user skipped the login/register process. This is an ugly hack an not a very future proof solution. I would like to centrally controll the pushing of vcs in one place and there cannot be any visible transition between them in that situation.
Is there any better/more robust solution to achieve this? I cannot have visible transition when returning back from one vc (this is animated) and the vc beneath it should push another on top of it while it becomes visible (no animation of this push). So it looks like we return to a completely different screen? No matter if it can be confusing for users, that is for another question.
EDIT 1: I am targeting iOS7 and newer only.
EDIT 2: Here is a sample demo which shows my issue. I directed the link to he main vc, which pushes other vcs in its viewWillAppear (the other vcs are not important). It is just for presentaion purposes.
This demo shows logs into console "nested push animation can result in corrupted navigation bar" and "Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted." which do not show up in my big project. I know what they mean, but how can I push a vc when antoher is popping away? The mentioned BufferedNavigationController does not work for me on iOS 7 (and it is not a problem, that it does not use ARC).
EDIT 3: When I start the provided demo for the first time, it will open the login screen instead of the main - good. Then after tapping the login it goes back to the main screen and should instantly push the another screen without the main being visible. It does not do that, the main is visible but the navbar thinks there is something above the main, thus the visible back button. It corrupts the backstack...
https://stackoverflow.com/a/20947860/1405008
Refer this for your first scenario like open login or other view controller.
For custom URL u can also use the same logic and check and present when its arrive from custom URL.
Always set the root view Controller will the easiest way to do this kind of different navigation stuffs in Your application also this approach avoid unwanted view-controller in stack.
I am writing an iPhone application using the storyboards for an initial mockup. The problem I have right now is switching view controllers.
I have a table view controller and another view controller. All I want to do is use a back button to go back to the original screen, and I can do that, except the data disappears. The storyboard that I have is shown below.
I have the Back button going back to the original navigation controller. I have also had it going back to the Card view controller.
I have hard coded some example cells to just see how things look and they show up just fine when I run the simulation. When I click the back button though, it goes back to the All Cards screen and the cells that were there are now gone.
If I need to post some code just ask for what part would be helpful, I have done all of this through storyboards though.
I'm sure it's something stupid I've done, any point in the right direction would be greatly appreciated.
Basically: you pushed where you should have popped.
What you are seeing on the Storyboard does not exist yet. By segue-waying during runtime to a view controller it gets instantiated.
When you segue-wayed during runtime from the Add Card view controller "back" to the Card View Controller - here is what happened: instead of popping the navigation stack all the way back to the Card View Controller you already had, you just instantiated a new Card View Controller and pushed it onto the navigation stack. You could verify that by going all the way back to the original Card View Controller by tapping the back button several times.
What you could do to accomplish your task is this:
Instead of using the Storyboard for your back button use an IBAction in code:
- (IBAction)popToRoot:(id)sender {
[self.navigationController popToRootViewControllerAnimated:YES];
}