I have a customer view controller that is a subclass of UITableViewController. It has a list that lists all the customers. I have a + button in the top right. I want to make it so when people click the + it will go to the add customer screen and after you click save it will act JUST like the iphone contacts list and then display the newly added customer.
Would I need to create a controller for each view? One to display the list, one to add the person and one to view the contact then another to edit the contact? Or should I use one controller and just add a bunch of views in IB into the single view controller?
Create a CustomerListController for seeing ALL customers.
Create a CustomerViewController for viewing and editing the detail.
Subclass the CustomerViewController calling it CustomerAddController for creating, as this will need a little more functionality.
Core Data Recipes application will give you some good pointers around this.
If you want it to only create the record after you hit save, you'll need to:
Create an additional NSManagedObjectContext, assuming you're using Core Data.
Pass that context to the instance of the CustomerAddController class only (not needed for the view class).
When the Save button is hit, you'll need to merge the two NSManagedObjectContext classes in the CustomerListController.
I believe the way the Contacts app does it is:
Contacts list is a UITableViewController in a UINavigationController
Touching the + modally presents (from the navigation controller) a different view controller for adding the contact
Touching Done pushes a new view controller onto the navigation controller for viewing the newly created contact, but it isn't visible yet because the modally presented contact adding view controller is on top. Immediately afterwards, the modal view controller is dismissed, revealing the newly created contact.
To answer your question, I'd suggest using three different view controllers, just like the Contacts app.
I suggest you to use different views for every task because using one IB file uses more memory where as if you use different IBs and view controllers for every task then there is not too much memory is used and after completing one task for example when you save the user detail free the memory for that view so that you app do not use much memory.
Related
I am trying to create a simple app and here is how it works:
When the user clicks the button "Picking", it'll show a tableview. And when the user selects a row in the table view, it will show the first view and display the data on the label.
I have 2 problems:
Every time I click the button "Picking", a new instance of the table view controller gets created; but does not reuse the existing one. How can I make it reuse the old one?
I want to pass the selected data to the root view. I tried by creating a segue to show the root view when user selects a cell and then passing the data on prepareForSegue method. But, I faced the above problem of memory leak. How do I pass the data between screens without leaking memory?
It sounds like you may be making a circular view hierarchy. When you tap on the cell in the table view, if you're pushing a new instance of the first VC, that is the wrong way to do it IMO.
Instead, you should pass the data back to the first VC then dismiss the second VC. Then, when you tap on the "Picking" button again, it's a new instance of the table view but your previous instance has already been removed from memory.
This allows for the smallest amount of memory to be used at any given time. When the table view controller isn't on the screen, it doesn't need to be in memory.
IMO, the best way to pass data up a navigation stack is to use a protocol and delegate. It's similar to how Objective-C protocols and delegates worked if you're familiar with that. Here is Apple's documentation on both. The delegate section is about 1/3 the way down the page.
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html
I have a navigation controller which I push a new tableviewcontroller for each received question to be asked to the user, so in stack it builds up to 30 controllers if there has been 30 question is asked.
The difficulty is that in some of the tableviewcontrollers I want to get the input from user by using another navigation controller inside that tableview: for example in the tableview(which is one the many views in the stack) there may be uitablecell with an arrow on the right saying choose the books you want to order, and when he clicks arrow a new tableview will slide in which includes the books to be choosen multiply with a checkmark, and then he will choose and back to main tableview and continue the main navigation there.
How can implement a new navcontroller inside the main navigation controller? or any better ideas?
EDIT: That can be an idea to push the detail view to the same controller, but then they will get popped immdidatly when user "backs" but I want to show the books (which are chosen in detail view) the main table, and when user clicks again to that cell, detailview will come with previous selected books. is this a good approach
Putting an UINavigationController inside a UINavigationController is a bad idea. What you seem to really want is persistence of state data after popping some of the view controllers off your navigation controller's stack.
I would put that state information into a persistent object. If it's a tiny amount of state data I may add that data to an existing object that I know is persistent, such as the app delegate or the root view controller. I would save a more complicated set of persistent data to a custom object. This object would be retained by the root view controller, and a reference would be given to each successive view controller. This object would have the data that may have been collected by a controller that was popped off the navigation stack and therefore no longer exists.
I don't really get why you dont just push the detailview of the uitableviewcontrollers to the main UINavigationController..
Could you explain that a little bit more detailed?
I have no rights to comment your question, so I am afraid I have to post this as an answer.
MfG,
SideSwipe
In my specific example I have a navigation controller inside tab 2 of a tab bar controller, the root navigation controller view has three buttons:
'nearest store' - this pushes a view that contains a mapview with nearest stores, clicking the store pins will push the store details view.
'all stores' - this pushes a view that contains a tableview that lists all the stores, clicking on a row will push the store details view.
'store search' - this pushes a view that contains a text box which allows a town/postcode search for nearest stores which appear in a tableview, clicking on a row will push the store details view.
The issue I have is how should the store details view be implemented since it will be pushed onto from multiple parent views.
I currently have each parent view, nearest store view, all stores view, store search view, contain a seperate instance of the store details view controller which is allocated memory and pushed onto the view controller as necessary. My worry is that if I access the store details view through each of these 3 paths then there will be 3 copies of the store details in memory since I am not sure when these will be automatically released.
My thinking was that an alternative way of implementing this is to have an instance of the store details view controller from the primary navigation root controller with the three buttons.
From any of the nearest store, all store, store search views, if the store details view needs to be accessed then the current view is popped off the navigation controller and a method in the root controller will be run to push the store details view on. This will mean that there will only ever be one instance of the store details view in memory since it will be reused everytime it is accessed.
Since the popping and pushing to get to the store details view will not be animated, it may be confusing for the user when they click the back button as they will end up on the root view controller and not the view they were previously on.
Is this a good way to implement this view structure? I am not sure I understand how the iPhone keeps views in memory and if going down this alternate route will be beneficial or a waste of time.
Thanks for any help.
What I would do (may not be right) is have a tab bar controller and the three different store search views under each of the tabs.
Then have a singleton view object which will be your details view. Therefore all three of the views can access the same details view object.
Hope I kinda helped :S
I have a table view that contains a list of Project objects. When an item is selected it brings up a detail view. Pretty standard. What is the best way to implement "add" functionality (popup a modal view controller to input new values and save the item)?
Currently I have view controllers for my root view, detail view, and add view. Essentially the detail view and add view are exactly the same except for a save & cancel button in the add view. Is it possible to reuse the detail view in the add view?
Finally, what is the best way to display the list of project properties in a grouped table view separated into sections?
Thank you for your responses.
Most likely, you are already passing your detail view controller a managed object that it is supposed to display when in detail view mode. When the user decides to add a new project, just create a blank object, pass it to the detail controller and display it. (You might want to insert this blank object into another "empty" managed object context in case the user cancels the add process to avoid having to clean up your main managed object context in that case.)
The detail view controller would also need a flag that tells it whether it is in edit or add mode so it can adjust its controls (and possibly delegate messages it sends to its owner) accordingly. You would set the flag to the appropriate value before you display the controller.
It sounds like you're looking for a UINavigationController. The UINavigationController lets you push new view controllers on top of existing ones. It gives you a navigation bar at the top that will allow the user to go back to the root controller. I think it's the kind of controller Apple uses it in the default email application, to give you an example.
Concerning organization: you design your root view controller and a detail/add view controller. In your app delegate, you attach a UINavigationController to the window and you set its root controller to the main controller you want to display. That root controller can then push the add/detail controller onto the stack (and when it does so, it can tell the add/detail controller which types of button to display.)
I can't answer your grouped properties question, but it sounds like a separate question anyway.
I'm diving into iOS development and am getting familiar with navigation view controllers. I'm trying to build a simple app with a table view that allows me to add objects to it. So far, I have a table view with an add "+" button in the nav bar that allows me to load my CreateObjectView and display it modally so the user can define the new object, but when they click the save button, I don't know how to send that object data back to the parent view that created the CreateObjectView that contains the object data.
When I create the child view (CreateObjectView), I could pass into it a pointer to the current view before I push it onto the nav stack, but this just feels dirty and circular.
I was reading about protocols and delegates and I could use that approach as well, but it also feels circular.
This question seems like it would be a common design issue to any tableview-based or nav-based app, how should I probably access the view that is one level up from my current view in a nav-based iOS app?
Thanks so much in advance for all your help!
It feels circular at first, but it is the right way. Before the UINavigationController pushes the new view controller you should set the delegate to the current view controller - assuming that's the object you wish to communicate with. Of course you could set it somewhere else instead, such as to a central Core Data handler. Then when you need to communicate call the delegate with the method you have defined. I've done several navigation apps like this after seeing Apple's cookbook example, and it really works well.