Is there a simple way to preload all the cells in a uitableview?
I need to do this in order to change whether or not all the cells are checked. If I just use cellForRowAtIndexPath, and the user say unchecks all the cells, and then checks a visible cell and starts to scroll again, either the selected cell gets deselected or the newly loading cells are selected.
It seems the easiest way to go would be to preload all the cells if possible.
Thanks!
Don't use the cells as your database.
Your cells are just a narrow window onto your data. The cells just show you a few of the objects in the underlying data. If you try to preload all the cells so you could then select them all, the UITableView could die a slow death, or slow crawl. Especially if we're talking hundreds of entries.
If you want to select all the items in your data, you do so with a direct call to your data to select its objects. Then, you reload the data into your TableView with a reloadData and if everything is set up right, your cells will show the selected state.
Read up on UITableView. Look at Apple's samples. You need to see the separation of data from the view and the controller.
Please re-read the answer I wrote here to your previous, similar question, which explains one solution to your problem.
Again, you should consider keeping an array of on/off settings. You can use NSMutableArray or a C array of int or BOOL values, whatever you want. But it definitely sounds like you need a data model.
Your -tableView:cellForRowAtIndexPath: looks up values of this array. Each value in the array corresponds in some way to a row in the table.
If you only have one section, then you can simply use the ith element of the array to set the checked state of the ith row of the table view. If you use NSMutableArray to store NSNumbers, you can handle resizing quite easily.
If you have more than one section, keep an array of arrays. Each top-level array corresponds to a section. Each inner array corresponds to a section's rows.
If you use NSMutableArray to store NSMutableArrays of NSNumbers, you can handle resizing and section addition and deletion quite easily.
The method -tableView:cellForRowAtIndexPath: then sets up cells with or without checkmarks, depending on the array's value.
Having a data model gives you the freedom to programmatically perform "select all" and "deselect all" button operations.
For example, when you click a button to "select all" cells:
Loop through the array and set each value to YES or 1 or whatever "on" label you chose originally.
Call [tableView reloadData], which is a method that goes back to -tableView:cellForRowAtIndexPath: and which will set a cell's checkmark state based on the state of values in the updated array.
No, you can't do this. You seem to be under the impression that a cell represents a particular piece of data, it doesn't. When the top cell scrolls off the screen it is usually recycled and brought in as the bottom cell. So a list that has hundreds of items you can scolled through may only ever have 8 or 9 cells alloc'ed and initialized.
You need to rethink your application's architecture. When you "uncheck all" it shouldn't change the visual state of the cell, it should change some state in the objects the cell represents, then when you load the cell for the object at that index path you should read that state and set the check mark appropriately.
The changes in the visual state of your cell should always be in response to changes in your underlying model.
Related
Having some issues with a tableViewCell freezing. I have a table view cell with a list of exercises. When I add a new exercise on another viewController, then pop back to this tableViewController that lists all the exercises, the respective cell gets frozen (see screenshot). Then, if I call [self.tableCell reloadData], that cell never refreshes.
it's weird because if the offending cell is, say, index #4, and I change the data source to only have 2 items, the 4th cell is still frozen. (the first 2 render correctly, the 3rd is blank, 4th is offending cell)
List of all exercises:
When I change the data in the tableView data source, that cell is still frozen:
If I put a breakpoint and inspect the tableView, it doesn't say anything about that frozen cell:
Not sure where to go from here :( It seems to only happen when I insert a row from a different viewController then pop back to this one.
Any thoughts? Thanks so much for any help!
You are keeping a reference to a cell. That is a bad idea. It contradicts the whole pattern of datasource and recycling of table cells. All kinds of wacky bugs will be the inevitable result.
Instead, you should make sure your datasource methods return the correct number of sections and rows, and the appropriate cells and then reload your table not a cell.
[self.tableView reloadData];
So, for example, when the view is returning from adding a new item, make sure the data array you are using is updated and reload.
I exactly don't understand your way of managing tableview along with data source. If you make any change in data source, same changes should be reflected in tableview as well. (Both should be synchronized). You can use:
Table reloadRowsAtIndexPaths:
Table deleteRowsAtIndexPaths:
Table insertRowsAtIndexPaths:
to make changes to your tableview and its cells. Or you can just call [Table reloadData]
Remember: never try to store references of UITableViewCells as they are dequeued again on screen - your reference will be just a trash. Just alter your cells using above 3 methods and you are good to go. If you want to clear something, just ask for it.
How can I update a tabelview cell when a particular notification received, without reloading table data. notification tells the id of the cell that I need to update. So I want to iterate all table cells and update only the relevant table cell without reloading it. how can i do this
Use [tableView visibleCells] to get a list of all cells that are displayed. Iterate through this array to see if the cell you need to update is displayed, then do whatever you need to. (this method is if you're reusing cells).
You can just use the built in reloadRowsAtIndexPaths:withRowAnimation: instead of trying to usurp the framework's functions. This will efficiently only reload the cell you ask it two not the entire table or even an entire section.
Reloads the specified rows using a certain animation effect.
Reloading a row causes the table view to ask its data source for a new cell for that row. The table animates that new cell in as it
animates the old row out. Call this method if you want to alert the
user that the value of a cell is changing. If, however, notifying the
user is not important—that is, you just want to change the value that
a cell is displaying—you can get the cell for a particular row and set
its new value.
When this method is called in an animation block defined by the beginUpdates and endUpdates methods, it behaves similarly to
deleteRowsAtIndexPaths:withRowAnimation:. The indexes that UITableView
passes to the method are specified in the state of the table view
prior to any updates. This happens regardless of ordering of the
insertion, deletion, and reloading method calls within the animation
block.
Available in iOS 3.0 and later.
I have an NSTableView with multiple selections enabled
If I select items and scroll the list back and forth they are remember and shown and selected (blue background).
Using the didDeselectRowAtIndexPath and didSelectRowAtIndexPath I am able to keep my own array of selected items.
that part works well.
However If I then use the sectionForSectionIndexTitle and jump to a letter The selection appears to be forgotten even indexPathForSelectedRows appears to have been reset and is now empty.
My own array remembers that an item is selected and I can set the cell.selected in the cellForRowAtIndexPath but the instant I move the list it is forgotten again
Any ideas is this a bug or how do you retain the selection list when jumping to a letter
Thanks in advance
Remember the UITableViewCells are there to display your data only and by no means they have a 1-to-1 relationship with your "model" as the are queued and reused when necessary (i.e. you may have thousands of items on display in a tableview but only a handful of instances of UITableViewCell allocated).
So you need to keep track of the selected / deselected items in a mutable array and make sure that you check for the presence of that item in your tableView:cellForRowAtIndexPath: method and then update the cell properties to represent your data.
By using an NSMutableArray of selected row values, it may be possible to keep track of the selected rows in the table yourself. Then it would be a matter of calling -selectRowAtIndexPath:animated on the last object in the array to restore the selections.
As for the bug: what could possibly be happening when the table jumps to a selected letter, is a stray -reloadData which would forget the selected row(s).
I think it is happening because your cells are reused. Do not reuse the cells(you are not using your cells efficiently). otherwise,
You can store the selection by yourself in an array and use it later for your purpose.!
I've been adding a temporary row to the end of my table view so I can limit the amount of data loaded / improve the speed of loading the view.
However, I didn't think about the delete feature. Where they swipe right to delete a row..
In my commitEditingStyle event I have, my check to see if it is a delete, then delete row from database, removeObjectAtIndex from my data array, beginUpdates, deleteRowsAtIndexPaths and if zero items left in my table insertRowsAtIndexPath with fade, so that my no transactions row will appear then endUpdates.
I did think when I add my tap for more rows I'd assign the row index to a variable and delete this row first in the commitEditingStyle event. However, I'd then have to query my database just to add another row, then add the tap for more rows row.
Which seems a lot of work for a quick fix.
Of course, I could just do a reloadData, but this seems really bad, but might be my only option.
I do eventually want to move to Core Data, but I really need to get this release out the door, its quite a complicated screen with segmented control for different data views and tap to edit the row in another view.
Can anyone advise me about some kind of trick / event I may have missed or another approach I could quickly use in this scenario ?
Make "tap for more" your table footer view instead of another cell. You will have to do this anyway if you move to core data and NSFetchedResultsController since hacking in an extra row becomes very complex then.
Your table footer view will just be a button (or some other view styled how you like it) - this can be created on viewDidLoad and set up with actions etc. It does not form part of your data model at all, so you have nothing extra to do in your datasource methods.
I have a table where there will often be two cells with the same title. I'm zooming in on a map whenever a cell in the table is clicked, so using the title as a unique identifier is out of the question. I already have a unique identifier, but I need to find a way to store it in a UITableViewCell object.
I have been considering two options, both of which are poor, IMO.
1) store the unique ID as the text inside the text of the detailTextLabel property.
2) build a custom UITableViewCell class.
I'm new to objective C, and I would essentially like to know if theres a third option that isnt as inefficient as #1, but not as involved as #2.
Thanks
Use the cell's tag property (works only if your identifier is an integer).
That said, cells already have a unique identifier (albeit not necessarily constant) and that is their indexPath, i.e. their position in the table. You should generally not use the cells to store any data directly. Instead, store the data in a model object and maintain the connection between model data and view via the indexPath.
This is especially important when dealing with table views as cell views get reused or deallocated as soon as a cell is scrolled off the screen.