iOS Swift 4 - how to pass data to splitviewcontrollers master - ios

If anyone is well experienced with split view controllers and can help me with, it would be a great help.
I have a project that begins with a login screen, followed by a search screen that calls an API to get the results. After the search screen gets the results from the API call, I want to pass those to a splitviewcontroller for display. Basically to the splitviewcontroller’s master, which has the table view. So how to do this? I don’t see how can I use performsegue, when the segue’s from splitviewcontroller to the master don’t have any identifiers?
So is it possible to use splitviewcontroller as your third or fourth screen?
Is there any alternate way to achieve this?
Thanks.

Every UIViewController has a property called splitViewController. This is an optional value that may or may not be nil based on if you are using a UISplitViewController. The splitViewController property will allow you to access the view controllers that the split view controller has embedded.
With UISplitViewControllers there are two main components, the master and detail view controllers. On iPad the master is the one that is on the left side of the screen and takes up the least amount of space and the detail will take up the large area to the right. On iPhone both will be on top of each other in a navigation stack and both will take up the entire screen.
This is how to access the detail from the master:
if let splitVC = self.splitViewController, let detailVC = splitVC.viewControllers[1] {
detailVC.doSomething()
}
And this is how to access the master from the detail:
if let splitVC = self.splitViewController, let masterVC = splitVC.viewControllers[0] {
masterVC.doSomething()
}
Keep in mind you may be using a UINavigationController or UITabBarController within your storyboard that the master or detail may be embedded within. In that case you do the same but cast those view controllers as either UINavigationController or UITabBarController and drill down within them to retrieve your true master and detail.

Related

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.

iOS - How to push to a view controller and maintain the correct "View Stack" when going back

I've got a single navigation controller that houses the primary view of the app (A dashboard of sorts) which then branches off to the other views in the app via segues etc..
There's a hamburger menu, which makes use of a Cocoa Pods sliding view controller. Basically, my question is is it possible to navigate to specific view controllers via the menu and maintain the correct "stack" going back. I'm aware you can just push to a single controller, but I'd like (if possible) to retain the view hierachy going back.
E.g.
There's a link in the menu to Page 1.3
I want to be able to push to Page 1.3
Then have the back button on that view to go to Page 1.2, then Page 1.1 etc..
I'm not sure whether this is standard practice in iOS apps, or whether it's better to adopt an Android esque approach and just add views to the stack, not worrying about trying to form the correct navigation structure when they go back through the views.
Hopefully all of that makes sense.
If you are happy to do it in code, rather than a segue, you can use the UINavigationController's setViewControllers:animated: method (see the documentation). You will need to instantiate the relevant VCs, initialise them with any relevant data/state, and then build an array with them in order from the root view controller to the top view controller:
NSArray *newStack = #[rootVC, ..., page11VC, page12VC, page13VC];
[self.navigationController setViewControllers:newStack animated:YES];
Then popping from page13VC will go to page12VC, etc, etc. You can get rootVC and any other pre-existing VCs using the viewControllers property of the navigation controller.
I meet the same problem in my project,here is my experience.
If you just want to do simple jump, you can try the three basic navigation function:
[self.navigationController popToRootViewControllerAnimated:YES]
[self.navigationController popToViewController:[[self.navigationController.viewControllers count] - mypopcount] animated:YES];
[self.navigationController popViewControllerAnimated:YES];
Bind the action with the button, you can do that.
But, if you want to do more flexible page jump in ios, you must consider:
First of all, you need to confirm that there is no direct data interact between these view controllers, which means you need coreData or other sqlite tools to store data, so the destination page can load data itself.
Secondly, you should consider the strategy, page jump means pop all viewcontroller and push a new one, or just pop or push a new one just on the navigation stack.
Good Luck!

Using segues right

I have read here a lots of questions and answers regarding segues and story board , and i became even more confused about the way i build the hierarchy between views
My questions are very basic and simple, and i think they may be helpful to others :
1.In a simple words, when should i use push , modal, or costume segues ?
2.When go from view1 to view2 to view3,how should i go back from 3 to 1? can i just drag a segue from 3 back to 1? and what happens with 2 and 3 with memory aspects in that case ?
3 when dismissing a view, why it always go back to the previous view? is there a way to make a segue that dismiss automatically the previous view ?
I think a very simple and short summing on the way it works would be so helpful.
thanks.
If you are using Storyboards and segues you may want to take advantage of exit segues for going back. In your example you want to go from View 3 back to View 1. Depending on how you got there, you may have multiple options to go back. For example, if you used a UINavigationController and pushed your way there, if View 1 is the rootViewController you could simply call popToRootViewControllerAnimated: and it would handle what is necessary to get from wherever you're at in the navigation stack back to the root. If View 1 is not the root you could opt to use the popToViewController:animated: API instead, assuming you have a reference to View 1 from View 3 which usually isn't ideal if you're keeping concerns separated. As Renish pointed out you do have the option of accessing the viewControllers property of your navigationController.
Back to Storyboards, for better or worse, they can handle this all for you via an exit segue. The storyboard configuration determines the proper way to go back to a view that you came from. Check out this great explanation in this answer, https://stackoverflow.com/a/15839298/250190
I think u want How to Go 3view to 1view.Simply make array of Your view controller.
How do I get the RootViewController from a pushed controller?
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/Reference/Reference.html#//apple_ref/occ/instp/UINavigationController/viewControllers
Use the viewControllers property of the UINavigationController. Example code:
// Inside another ViewController
NSArray *viewControllers = self.navigationController.viewControllers;
UIViewController *rootViewController = [viewControllers objectAtIndex:viewControllers.count - 2];
This is the standard way of getting the "back" view controller. The reason objectAtIndex:0 works is because the view controller you're trying to access is also the root one, if you were deeper in the navigation, the back view would not be the same as the root view.

Using a UINavigationController for a set path without Back options

I am using a UINavigationController within my app (as expected) for a specific path the user takes when taking a turn in my turn based game.
When they move through the turn controllers they do not actually have the option to go Back from the Navigation Controller. This is planned/expected behaviour.
My question is, is it best to keep the other controllers on the UINavigationController stack when they are not going to be used again.
Should they be de-alloced immediately, or wait for the whole turn to be complete and let them go when the navigation controller goes (how it is at the moment). Some of the controllers hold data/images etc as properties so I am wondering if it would be more efficient to get rid of these on the fly?
If it is, what is the best method to load new controllers into the UINavigationController at present I am using self performSegue... or buttons that push to the VC from the storyboard setup.
You can manipulate navigation controller viewControllers using this code
NSMutableArray *viewControllers = self.navController.viewControllers;
//remove or add in the array
[self.navController setViewControllers:viewControllers];

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