How to manage multiple viewcontrollers in Xcode - ios

I have been working on an app which has a slide menu which is there for an easier travel from vc to vc. Here I found a tutorial on how to implement the menu, but I have problem to switch vc's, bcs I don't know how to connect them without getting errors. What I have tried so far:
All VCs to the menu and from the menu to the VCs. This worked, kinda, but I am getting the error: ...whose view is not in the window hierarchy!
From the menu to all VCs with unwind instead of a separate segue. Here I have a problem, where I don't know how to get to the menu... I tried to unwind it, but that also doesn't make sense, bcs I haven't performed a segue before it.
Here is how I have done the linking so far:
Thanks for your help.

I think you should download full example from git. And review finished project carefully.
The error what you got related that in some time you remove your root view controller or try to push without any navigation controller.
The better way if you will use the similar scheme, where navigation controller is a root controller.

Related

Why my navigation controller make transitions modally instead of push now?

Looking for help with some problem which i clearly don't understand since i'm just beginner here so please help me out if you can.
Here is my issue, so far i built all views through storyboard and all are showed by navigation controller using "push" segue set up in storyboard, till now everything worked as expected.
In some point i decided to add calendar view in the bottom half part of the main view controller to show up when user press the button. Following some advices found online i decided to add it as a child view controller (and did it programatically).
Here is the code i used to present the view:
addChild(calendarVC)
view.addSubview(calendarVC.view)
calendarVC.didMove(toParent: self)
and here is the code i used to dismiss the view:
willMove(toParent: nil)
removeFromParent()
Everything works great so far, but here is the catch:
after triggering removeFromParent() part, transition between every other view controller changed from push to modal. Almost like i lost connection with navigation controller somehow?
I don't know, and my knowledge level is way too low to figure it out myself, any attempts on finding answer here by searching similar topics also didn't give me any answer i can understand, so hoping someone can shed a light on my problem here.
Thanks
make sure you invoke willMove(toParent: nil) removeFromParent() from child view controller.
Invoking the above functions from a parent view will remove the controller from the Navigation hierarchy.

Linking To An Embedded VC in A Container Of A VC Embedded In A UINavigationController

I have the following storyboard structure:
Essentially I have a UIButon that I want to link to the "TargetTableViewController" via an IBAction - NOT by 'Ctrl+Dragging' but programatically by way of some code instead.
I believe I have to present "NavViewControllerTwo" as a NavigationController (as it 'holds' "HoldingViewController") and have tried various renditions of this via the many threads at StackOverflow. But this did not work.
I suspect it is because the actual "TargetTableViewController" is embedded in a ContainerView of "HoldingViewController" and that causes the problems.
I have tried implementing other renditions of presenting "TargetTableViewController" as a child of the "HoldingViewController", but that caused me more problems.
I realise I may have over-complicated things here, but the reason for the container is I want to display a BannerView at the bottom of my eventually presented view.
If anyone can be kind to point me in the right direction, I will be very grateful. Thank you for your time.
** CLARIFICATION **
I am actually trying to present "HoldingViewController" as that would effectively display my "TargetTableViewController".
Please refer to amended image below:
Apologies for the confusion and lack of clarification.
Setup a segue from MainViewController to NavViewControllerTwo in the storyboard, give it an identifier and then perform that segue from your code on the button press action using [self performSegueWithIdentifier...

Correct way of removing (deleting) a view/viewController from the stack after segue in Swift

I am running into a problem here. I am presenting views with performSegueWithIdentifier. Everything goes smoothly. The problem is that as a test, I only have 2 viewControllers with some data in them and I have two buttons that call a segue back to the other VC. If I keep performingSegues, you can clearly see that the memory usage goes up every two segues by around 0.4Mb. This tells me that the Views are not being deleted/removed from the view stack and are just using memory. I would like to know the correct way of getting rid of the view that presents the other view by using performSegueWithIdentifier (of course, after it finished presenting the view, else it will not work I guess).
Could you point me in the right direction? I found some objective-c code that tried to do this but it was very extensive and I don't know much about objective-C, so it was a little hard for me to understand.
Thank you in advance for your help!
Cheers!
Edit:
I am doing a "manual segue". By this I mean I have two view controllers standing on their own. They are not embedded in any navigationVCs or something like that. I am using an "Adaptive Segue" of type "Show".
If your goal is to always keep one VC, and since you already have a manual segue, what you can do is, after presenting the next VC you can pop the existing VC from the root and assign the destination VC as your root VC like so
class ManualSegue: UIStoryboardSegue {
override func perform() {
sourceViewController.presentViewController(destinationViewController, animated: true) {
self.sourceViewController.navigationController?.popToRootViewControllerAnimated(false)
UIApplication.sharedApplication().delegate?.window??.rootViewController = self.destinationViewController
}
}
}
When you do normal segues, you are piling up new view controllers on top of the existing ones without dismissing them. That's why your memory usage keeps going up.
You need to provide more information before we can give you specific guidance. Are you doing modal segues or pushing onto a navigation stack?
If you're pushing, you want to pop to the view controller you came from. Think in terms of a stack of plates. When you push, you add plates to the stack. When you pop, you take plates off and reveal the plates (view controllers) underneath. Do a search in the Xcode help system on "PopTo" to find the methods that let you either pop back to a specific view controller or back to the root view controller of your navigation controller.
Modal view controllers stack on top of each other in a similar fashion, but without the origination of a navigation controller. If you've pushed a series of one or more modals and you send the dismissViewControllerAnimated:completion: method to the view controller you want get back to it will dismiss the modals that are on top of it.
You can also look at using unwind segues. Unwind segues let you go back where you came. Do a search in the Xcode help system on "Using unwind segues" for more information. Most of the tutorials on unwind segues are written in Objective-C but you should be able to find some in Swift if you look. Explaining unwind segues in enough detail to be useful is more than I can cover in this answer.

Programmatically calling performSegueWithIdentifier does nothing

I am in a situation exactly like this post, but for whatever reason, only one of my performSegueWithIdentifier:sender works.
I have a View Controller (embedded in a UINavigationController) with two buttons, Cancel and Done. When clicked I want Cancel to unwind to one screen, and Done to unwind to another screen; however, this only works with one of the two segues I have set up.
- (IBAction)clickedDone:(id)sender {
[self performSegueWithIdentifier:#"unwindToHome" sender:self];
}
- (IBAction)clickedCancel:(id)sender {
[self performSegueWithIdentifier:#"unwindToViewEntries" sender:self];
}
"unwindToHome" works fine while "unwindToViewEntries" does nothing. No error, no printing, nothing. If I switch the segues and buttons, "unwindToHome" will still work while "unwindToViewEntries" does nothing.
I have unwind methods in both ViewControllers I want to unwind to and there are no other actions attached to the buttons.
I find it really odd that only one works. I've looked them over several times and there is nothing different that I can see.
Thanks in advance for the help. If there are some more things I should check please let me know!
I've already looked at solutions for the following posts:
How to unwind programmatically to 2 different VC
performSegueWithIdentifier not working
I've also tried removing the segues and re-adding them, as well as deleting and re-adding the entire view controller. Every time, the same behavior.
EDIT: I should also mention that I've tried adding other segues in different views and none of the new ones I add work. Only "unwindToHome" seems to work, and I can't figure out why.
In the storyboard make sure that both segues show that it is a show (push) segues. There was a question earlier,which is a little bit different, that if you create two segues from the same button Xcode was setting one push the other modal.
Happy coding!
Yan

iOS iPad Master-Detail controller drill down

I am trying to create an iPad app with a master detail principle, so I am using the UISplitViewController. The issue is that I want a different behaviour for the app because sometimes the detail view goes deeper. So I want the detail view to become master view and load a new view as detail. To give you an example lets say I have a ViewController1, ViewController2 and ViewController3. When a link from the (master) ViewController1 is clicked, ViewController2 (detail) should be shown next to it. Now if the user clicks a link in ViewController2, ViewController1 should disappear ViewController2 should take its place and ViewController3 should be shown. What is the best way to do something like this cause I can't do that with a UISplitViewController.
By default, a split view template gives you a navigation controller for both the master and detail sides. I'd look at creating a ViewController2B that uses the same data model as ViewController2 and then synchronize push/pop so that 1 & 2 switched with 2B & 3 as one operation.
Ok. I get the issue now. I'm not quite sure if this is helpful at all, but sometimes these custom controls are quite helpful. Have you checked them? They might help you implement the code in your own project or just use them maybe?
https://github.com/mdznr/MTZSplitViewController
https://github.com/mattgemmell/MGSplitViewController
https://github.com/sergik-ru/SMTabbedSplitViewController (Slightly different)
Hope that helps.

Resources