I currently have a navigation controller in my project.
The user is presented with 3 tables, one at a time, within which they can select some options.
My issue is that if a user makes a mistake and wants to go back to the previous table, the option they chose is no longer selected. This causes them to select it again - which creates duplicates in an array that stores data.
How can I have the table retain the selection so that if the user goes back to the previous table the option remains selected?
Are you using UITableViewController for your tables?
From Apple's documentation:
In -viewWillAppear:, it reloads the table's data if it's empty.
Otherwise, it deselects all rows (with or without animation) if
clearsSelectionOnViewWillAppear is YES.
So probably you will need to just set clearsSelectionOnViewWillAppear to false on your view controllers and hopefully everything will work as expected.
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
What is the preferred method of creating detail view controllers for table rows? Let's say I have a UITableView with 100 rows in total. Each row can show a detail view controller. Should I re-allocate a new detail view controller for each row selected, or can I re-use the existing one using some sort of reset method?
Right now I have both options present in my code:
For side swiping, I reset the same controller using a short fade animation.
For Core Data UITableView, I allocate a new controller for each row.
Should I try to reset the UITableView's detail controller when rows are selected, or is it a bad practice?
Update:
I ended up allocating the controller for each table row selected. Within the controller, I added 2 extra buttons with fast forward and reverse icons. These allow the user to traverse the table data one by one, viewing all the details. I found that going back to the table to select one row after another to be too tedious.
The extra buttons reset the controller for next/previous event. Since I'm using only one controller, I cannot user Core Animation to perform a view transtion. Instead, I scale the buttons on the controller to indicate that something has happened with "fast forward" has been tapped.
thank you!
I think the answer to your question depends on a number of factors, but it's definitely a very good thing you have both options currently present in your code. This gives you a chance to run Instruments and do a bit of memory profiling and allocation tracking.
The way I'd do it would be to check out what the difference is in memory between opening up one detail view controller and then instantiating 10, 20 or even all 100 detail view controllers.
If the memory footprint increases dramatically, I might be inclined to do the "reset the detail view" route.
If there's really only a small increase in memory for each detail view created (and it's faster to not have to reset everything on each table row selection), then I'd go that route.
I have a TableViewNavigationController. On my first page, i have displayed a table-view, and on the navigation bar there is a add button, where the user could add a record.
once the user clicks on the add button, a UIView will be displayed and the user could enter details and submit, and then when the user clicks on the back button on the TableViewNavigationController, the first page which contains the table-view is displayed with the added record.
But, for me multiple records are displayed, and when i restart the stimulator it shows the correct set of records. Why is this and how can i prevent this?
EDIT : Can someone tell me which method fire's when we click the back button of the TableViewNavigationController ?
Are you updating the datasource of your tableview with the right array-data?
If not,
[yourTableView reloadData];
Should fix that.
You likely need to use the reloadData method for your tableView when returning to the table. And possibly refresh your data. Is it coming from an array or using fetched results controller? Either way, it sounds like you're seeing odd results because the data has changed.
You should show us some code, so we can help you more.
The method that get's called when you change a view is the viewWillAppear
Since you mentioned that you are reloading your Table Data Source, are you sure you are adding the new entry to your existing Data Source (your Array) ?
Is your Array an mutable Array, so you can add the new record to it?
I have a tab-Bar Controller + UINavigation Controller app.
In tabs 1,2,3 I have table views that offer the user some items to choose from. Once the user selects the items they get added to a Cart.
Tab 4 is a table that shows the items in Cart.
I noticed that when the user selects items in tabs 1 or 2 or 3 they show ip in the cart tab the forst time its clicked on.
If the user then goes back to tabs 1,2,3 and selects more items, the table in the "Cart" tab does not get updated.
Im not sure why this is the case. I have programmed in the "Cell for Row # IndexPath" method to get data from the Datasource each time this method is called.
Im puzzled. Wondering if there is something obvious that Im missing here?
Thanks for your help
The table only updates its data in two situations.
You're using an 'NSFetchedResultsController' to bridge the gap from your data to the view. This controller automatically updates the view whenever the underlying data changes (and, similarly, automatically updates the data when it receives an add/edit/delete request from the view).
You handle it all manually in your own code, most importantly calling the UITableView's reloadData method after the data in the datasource has changed.
you have to reload the data in the table view friend .
[yourtable reloaddata];
use this where you want to show your data
I have a ordinary UITableViewController inside a UINavigationController. The former includes a searchbar which is connected to a search display controller. I use the standard behaviour, i.e. when the user enters any character the search results table view overlays the normal table view.
Now, both table views act inside a navigation controller. If I select one item from the search results table view, a new uitableviewcontroller (with specific information about the item selected) gets pushed onto the nav stack. When I hit the back button on that controller, I observe a strange behavior: The section headers of the normal table view overdraw the section headers of my search results table view. They are displayed as if my normal table view is being displayed (I can see that from the number of rows between the headers, though the rows remain empty). The search result table rows are still being displayed.
This behavior comes from the fact that I reload the table view on viewWillAppear. I do this to react on changes in the database made by the user at some other point in the application or automatic background data updates. I already tried to poll if the recently displayed table view is being shown via
(self.tableView == self.searchDisplayController.searchResultsTableView)
but that statement is always false after I return to my normal table view controller.
The question: how can I poll the correct state of my table view to avoid the displaying errors?
The UISearchDisplayController class implements an active property. Guess what it's used for :-)
e.g. just check for (self.searchDisplayController.active) or ([self.searchDisplayController isActive]).