so I am building a simple chat app. I will have a login screen, register and later on a UITableViewController so show the friend list. I'm not sure if I should use a UINavigationController for this or just stick to UIViewControllers. Below are two images for the potential setups.:
and:
I'm just wondering is it generally better practice to use a navigation controller? I am also a little confused about what happens to a view controller when it is popped. Does [self.navigationController popViewControllerAnimated:YES]; keep the view controller in the memory to be accessed again later or is a new one created each time? The same question for [self dismissViewControllerAnimated:YES completion:nil], is this destroying the controller or storing it for use later? Thanks
I'll give you my opinion about when to use a navigation controller.
If your app need to present its content in a hierarchical fashion (Master/detail) is pretty common to use a UINavigationController.
If you need to present some content that is not strictly related with the presenting content you can present it using a new view controller on top of it.
Regarding the memory, as soon as you don't keep any reference to the controllers either presented or pushed once remove (popped / dismissed) you loose any reference to them so no space used in memory
I think you will stick to the UINavigationViewController. Simply because the login and registration are belonged to your user management. From the UX standpoints, it's better to use Modal if the scene you are going to present is somehow irrelevant to the current scene. Therefore, go with UINavigationViewController for your situation.
The second question is related to memory management. It's kind of like the reference counting. If you have something to reference the UIViewController, its reference counting won't drop to zero which mean the system won't clean this up. So, you still have way to get then. If you just simply pop then up or dismiss it without referencing it. The reference counting will become zero and the system will clean it.
Note: If you want to simply display a view controller which doesn't need hierarchical navigation or a navigation bar then you wouldn't need to use a UINavigationController.
But in this case I would still suggest to use UINavigationController for the simple fact that your use case (Login Flow) can be completely addressed using a navigation flow.
In terms of memory there is now difference. Feel free to use any of them in this concern. Although how these views are presented has difference.
Related
In an iOS app, to move between screens, I can either present a new ViewController ("move forward") or dismiss a current ViewController ("move backward").
In my naive understanding, this is simply a way of moving back and forth in the stack of ViewControllers kept by the app.
I have an intuitive preference for dismissing a ViewController (where possible) rather than presenting a new ViewController. It gives me the feeling of operating within a finite set of ViewControllers which in turn makes me feel the app is memory efficient.
Say I am on View A and want to show View B, then presenting A would result in a stack A-B-A whereas dismissing B would keep the stack at A.
My question is this: is that justified? is there any (programmatic) downside to perpetually working by presenting new ViewController? Is it memory inefficient?
I wonder how many previous Views are being saved by the app and how long the stack could get, and if that is a reason to dismiss whenever possible.
I am not 100% sure if i understood you correctly, but it seems in-efficient memory wise and not sure how possible it is. You want to keep going backward basically, just dismissing views, right?
Meaning when you load B, then A, then you want to dimiss A to go to B again? Am i understanding this ok?
In that case views would have to be in a constant "stack" and i am sure it will make things go slower, but more imporatantly, from user perspective and user experience, something that they are not used to at all :/
My understanding would be: If you want to show A again, then you should be going back to the instance of screen A that you already have. There might be special cases where it makes sense to have multiple instances of A (like detail screens for different objects), but even then: What you definitely should not do is build a never-ending stack of view controllers because as you already assumed: This will consume lots of unnecessary memory.
Maybe you should take a look at existing apps or the Apple Human Interface Guidelines and try to understand better how their view hierarchy works.
I got some serious problems understanding the viewcontroller stack.
When will my app use a stack to save the previous viewcontrollers? Only if I use a navigation viewcontroller or anytime I use normal viewcontrollers and segue modally between them?
So I was just wondering if I use some sort of chained routine for example, like going from vc 1 to vc 2 and from vc 2 back to vc 1. No navigation controller, just modal segues, no unwinding.
Does my app got performance issues because of a stack (which will grow everytime I go around) or doesn't it make any difference?
----updated
So basicly this is my problem. If I went through the routine of the app, the views get stacked everytime I do a transtition.
UINavigationController will retain any controller you push onto it's navigation stack until you pop it back off.
Any UIViewController will retain a controller it presents modally until that child controller is dismissed.
In either case every controller will at a minimum consume some memory until you remove it. Apps which construct ever expanding stacks of controllers are likely to encounter a number of issues including:
you will eventually run out of memory, how fast depends on how much memory each controller uses.
you may see unexpected side effects if many controllers in the background react to the same event.
users may become confused if they change state in an instance of controller 'A', push an instance of controller 'B' on top of it, and then "return" to a second instance of 'A' added to the top of the state. Since they're looking at a new controller and view whatever selection, scroll position, user input, or other state they set on the previous instance may be lost.
developers, including you, may come to dread touching this app.
I suspect that everyone will have a better experience if you view controller management matches whatever visual metaphor you are presenting to the user.
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/
I have a CoreData app with the MainView the UITableViewController which houses all of the items in the list. What i'm trying to accomplish is adding a custom back button and using the popToViewController:animated: to access the settings. When I try to use this method the app crashes. After doing extensive reading I realized that push and pop use an NSArray stack for view controllers. For example, the rootView is view 0, when you use pushToViewController:animated: it added in another view, 1 and so forth. That all made sense. What I learned was you can't pop to a view which is not loaded into the stack after the root view. My objective here is to pop to the settings view. When I change the code around in the AppDelegate.m to make the SettingsViewController the rootViewController, the UITableViewController no longer functions, it fails telling me the entity "enityName" can't be initialized. Is there any way to still have the CoreData part of the app function correctly and still pop to the settings? I have thought of using a modal view but it ruins the style of the app.
This was quite hard for me to explain, if you didn't understand any part of it, let me know.
Thanks for your help.
Update: I read in the UINavigationBar documentation that you can use - (void)setItems:(NSArray *)items animated:(BOOL)animated thus allowing you to manually set the array of pushing and popping view controllers. I just can't figure out how to do that. I've gone through apples drillDown sample code, but it didn't have the functionality I was looking for.
Perhaps you are misunderstanding Apple's navigation controller idiom. It is meant for drilling down a hierarchical structure of views and move back and forward easily and intuitively.
A view that is outside this hierarchy (it seems your Settings View belongs to this category) should really be presented modally. On the iPad, you can even use the pretty and convenient UIPopOverControllers.
Of course, if you want to keep your own look and feel (incurring the danger of confusing your users), you could fiddle with the transition animation. You could use Apple's own and thus pre-approved UIModalTransitionStyle property of UIViewControllers.
Or you could try what you did up to now and fiddle with the view hierarchy. Maybe you can eliminate your errors simply by using the view controllers sequentially and not jumping around skipping controllers in between. In this case it should be enough to use
[self.navigationController pushViewController:controller animated:YES];
and
[self.navigationController popViewControllerAnimated:YES];
rather than the more error prone versions pushToViewController and popToViewController.
I'm trying to get a better understanding of creating complex navigations with the UINavigationController. Please, If I'm wrong in any assumption (which is so possible) just let me know.
As far as I see, it seems that UINavigationController is specifically designed to achieve a kind of navigation where pushing a new controller provides a more in-depth detail of data in a "linear" way. You can go further in the navigation by "pushing" or back "popping" the controller.
However, it's usual that the application has in every view a way to go to another view which doesn't have to be the parent and can be in previous levels of the stack (or simply doesn't exists yet). Such applications tend to let the user go anywhere he wants, which seems to conflict with the way UINavigationController works.
It seems obvious to me that if I start to push controllers without control I'll have memory problems.
How can I, for example, go to a view which is two levels down in the stack (for example, what a "Home" button would do)?. Should I save some controllers/views as the initial in a singleton variable for better access and avoid memory problems?
You can use popToRootViewControllerAnimated: to get back to the root, or popToViewController:animated: to pop back to an arbitrary previous view controller. You can also use setViewControllers:animated: to directly set the entire stack of view controllers.
Do be careful not to confuse your users, however.