Moving UITableView cells and maintaining consistent data - iphone

I've enabled editing mode and moving cells around to allow users to position table view content in the order they please. I'm using Core Data as the data source, which sorts the content by the attribute "userOrder". When content is first inserted, userOrder is set to a random value. The idea is that when the user moves a cell around, the userOrder of that cell changes to accomodate its new position. The following are problems I am running into while trying to accomplish this:
Successfully saving the the new location of the cell and adjusting all changed locations of influenced cells.
Getting the data to be consistent. For example, the TableView handles the movement fine, but when i click on the new location of the cell, it displays data for the old cell that used to be that location. Data of all influenced cells gets messed up as well.
I know I have to implement this in:
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {}
I just don't know how. The apple docs are not particularly helpful if you are using Core Data, as in my situation.
Any guidance greatly appreciated!

Problem 1 is pretty much independent of using CoreData, just think of a simple array:
{0 1 2 3 4 A}.
Now the user moves some freshly appended element A within the Array:
{0 1 A 2 3 4}
So starting with the inserted element A, which receives the index 2, all elements need to have their index (which is userOrder in your case) incremented by one.
So you map 0->0, 1->1, A->2, 2->3, 3->4 and so on.
Problem 2 may have two or three sources:
Either your CoreData values are not synced so the database is not in sync with what you see.
[table reloadData] was not called
Your move-Algorithm is wrong
So perhaps you can check the thee points above and if none applies you could consider posting your move-algorithm for closer examination.

Related

Saving Order on UITableView data

I have created a reorder-able UITableView. I am loading data from Realm, and showing that data into UITableView. My UITableView has Section and rows.
now User can hold Any cell in any section and can reorder them in 2 ways
User can reorder cell with in the same section.
User can reorder cell across the different section.
What I need:
Once the user has made the order he should see same item in same order
when he come back to App. For any type of reordering I have to do
indexing. But I do not have clue how to reorder them in database.
My Idea to resolve the requirement
My idea is to include the String type value in the Model where I can replace something like (1,10) that will indicate section 1, row 10.
But I do not have idea how to tackle this and how to save the reordering as i need here. Any idea about that?? please share

UITableViewCell is frozen (not rerendering with new data). How to fix?

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 to keep UITableView's datasource ordered in response to user moving rows around?

I have a UITableView and one of its sections is managed by a NSFetchedResultsController. It fetches core data objects and keep them sorted by the "order" attribute:
object with order 1
object with order 2
object with order 3
The requirement that I'm facing is that the user can move rows around. After move:
object with order 2
object with order 1
object with order 3
What do I need to do to ensure that the managed objects in core data reflect changes in order resulting from user moving table view rows around? When I'm working with GMGridView, there's a callback that exchanges two objects. In such case, changing their order works, but I do not see such function for a UITableView.
Would I need to manually change the order attribute for all objects that exist below the moved row?
You can use this:
- (NSIndexPath *) tableView:(UITableView *)tableView
targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
Plus re-ordering your data-source, by exchanging the objects order.
You need to store an association between the fetched object and the 'row order'. You order the rows based on row order; the row order defaults to your 'order' attribute. When the user moves a row, you update the 'row order' as well.
You can maintain the association either in the CoreData object itself (add another attribute) or by mapping the fetched object to its row order (in NSUserDefaults or in just a NSDictionary).
Moving rows around does not just affect the order attribute of itself but all the rows behind it. A work around I have found is to copy the fetch request objects to an nsmutablearray then moving the object within this array. Then running a for loop and updating the order attribute in each object then saving the managed object context. Then reload the uitableview. This seems like a lot of work but currently moving objects in a fetch request is not automatic like insert and delete. I hope this helps!

Is it possible to preload all the cells in a uitableview?

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.

Is it possible to get array of all index paths for the cells in a UITableView?

Is there a simple way to get array of all index paths for the cells in a UITableView?
Since you are the one that told the table view how many sections and rows per section you had, you can use that same data - or in fact even call the same methods on your data source to ask that question from elsewhere.