I have a UITableView that has several cells of various heights. Each of the cells has itself a table of cells (here i am manually handling adding and deleting UIViews) that can be edited or deleted. The problem is that any time I edit one of the inner UIViews in one of the UITableViewCells, it is immediately reset to its original data that was given to it at instantiation when i call [tableView reloadData] on the tableview. If I don't call reload data, all the data looks great, but the height of the row is too large if i happened to have deleted a row from my UITableViewCell class. I've tried everything I can imagine, calling setNeedsDisplay, removing and re-adding to subview, and creating the cell every time, without using dequeueReusableCellWithIdentifier. None of these have done the trick.
Any idea what could possibly be going wrong??
Thanks so much!
Related
Struggling to find where fault is with my code. On first view load, everything works and loads fine as it should, but when i revisit that view, it seems that the first two cells are empty. I logged the dictionary (dict) in viewWillAppear: and it logs the data fine, so error has to be in cellForRow method. Take a look at my method, and see where i'm going wrong, the third cell populate third piece of data, so i'm totally stumped, but the first two cells are completely blank, no data.
http://pastebin.com/Va84MG5g
First of all, why are you doing all of that insane UITableViewCell customization inside of your tableView:cellForRowAtIndexPath: method? Create a custom UITableViewCell subclass and do the set up there.
In the class's initWithStyle: method, add all of your subviews with a frame of CGRectZero, because at initialization, the table view cell doesn't know how big it is. You can set text alignments, colors, etc. here as well. Then, in layoutSubviews, go ahead and set all the frames. Override prepareForReuse and set things like your UIImageViews to nil. This will help with performance for reused cells.
As for why you're not seeing your data in your first two cells, my initial thought is that it has something to do with the way you're setting up your cells for reuse. You're asking your tableView to dequeue a regular UITableViewCell and only creating all of these subviews if the returned cell is nil. So what happens when it returns a UITableViewCell? You skip the part where you alloc/init all these subviews, and so you're basically adding nothing to the cell. I feel if you create a custom subclass and ask your UITableView to dequeue that instead, you'll get the result you're looking for.
NOTE: If you're targeting at least iOS 5, you can create your UITableViewCell's layout in a nib and register the nib with the table view. Doing so will guarantee that you always get a dequeued cell, and you never have to do your if (cell == nil) check. If you're targeting iOS 6, you can register a UITableViewCell subclass.
I know this question had been asked hundreds of times before, but it's never really been solved (Or at least the way I'd like it to be). I have a rather complex UITableViewCell setup. The cell.backgroundView is loaded from a UIView subclass which uses a fair bit of CoreGraphics and CoreText. The code is rife with CTFramesetterSuggestFrameSizeWithConstraints, so I'm relectant to duplicate the class in the heightForRowAtIndexPath method.
I think I can solve this by creating an NSMutableDictionary with the indexPath as the key and the height as the value. But then I'm faced with the problem of heightForRowAtIndexPath being called first. I believe I can solve this problem by guessing the height of the cell and then once the cell's UIView subclass has finished rendering, use delegation to set the cell's height.
But this leaves me with the problem, how the hell do I delegate this? And, how to I prevent scrolling from being extremely choppy? as the cells will be created and resized in a split second.
In the past, I've used a dummy cell. I have a separate method -fillInCell:forRowAtIndexPath: which puts data into the cell. That way I can fill out the dummy cell in -tableView:heightForRowAtIndexPath: and the real cell in -tableView:cellForRowAtIndexPath:.
If this does not work for you then there are other options.
The first thing that comes to mind is create real cells in -tableView:heightForRowAtIndexPath: instead of -tableView:cellForRowAtIndexPath:. You can store completed cells in a mutable dictionary. -tableView:cellForRowAtIndexPath: will simply pull the completed cell from the dictionary. You should also detect when scrolling has stopped so you can empty your dictionary (just because -tableView:heightForRowAtIndexPath: was called doesn't mean -tableView:cellForRowAtIndexPath: will get call for the same indexPath).
Hope that helps.
I'm working in Objective C. I have a UITableViewController with about 25 cells that push to a UIViewController. When the user hits back, I want to see if the user entered the correct data for the given cell. (I have a working bool , we'll call it isCellComplete for now). If isCellComplete is true, I want to add a checkmark as the accessory to the cell. I've been trying to put the test in cellForRowAtIndexPath but that method does not seem to run and refresh the cells everytime the view appears. Anyone have suggestions?
You should look into the UITableView method reloadRowsAtIndexPaths:withRowAnimation:. This is much more elegant than reloading the whole table view. And if you don't want an animation, you can specify UITableViewRowAnimationNone and it will look just like reloadData but be much more efficient.
You should do the check in tableView:cellForRowAtIndexPath: and if the check passes, set the cell's accessory to UITableViewCellAccessoryCheckmark. Then when you tell the table view to reload the appropriate row(s), it'll automatically call tableView:cellForRowAtIndexPath: on the data source and update that cell.
You could just call
[self.tableView reloadData];
in
-(void) viewWillAppear:(BOOL)animated
And that will make cellForRowAtIndexPath be called again when the view appears
I have an app where the user can drag UITableViewCells from one TableView to another. I do this by rendering a "dummy" cell on top of the UITableViewCell that the user touches, and disable the "real" cell. I then insert a new row in the destination UITableView, after I have animated the dummy cell, to the position where the new cell will be inserted. This works as i want it to. But the other way around, causes me a lot of issues.
When a cell from the destination UITableView I double tapped, the cell should animate back to the source UITableView where it initially was dragged from. The problem is that I cannot remove the cell from the destination UITableView fast enough.
I want it to disappear instantly, so that when I render a dummy cell on top of it, I won't see an 2 different animations of the same cell. (the one where the dummy cell moves to the source UITableView, and the one where the actual cell is removed from the destination UITableView).
A reloadData on the UITableView is not good enough, because I still want the remaining cells to pull together on the now empty space, with an animation.
So, can I somehow create a custom animation, or set the duration of UITableViewRowAnimation to zero? UITableViewRowAnimationNone does not do anything for me.
Oh, and it might be important to mention that the app is not going on App Store, so I don't care if iI have to do something that Apple will not approve of.
In my iPad application, I am inserting some value on a label. That value should also appear on a UITableView in another class. When I insert the value in the label and navigate to another view, there is no value appearing on the table view but when I scroll the table view up and as it comes to its original position, the value appears. How can I fix it?
Thanks and regards
PC
When you scroll the table you are eventually reloading the data as things become visible. If you call [tableView reloadData] on viewillAppear this should get the label refreshed and displaying correctly for you.
Good Luck!
Check out the reloadData method in the documentation. You will need to call this method after changing the value so the table knows to reload the cells currently being displayed. As you scroll up the cells are being redrawn, which is why you see the new value after a scroll.
Just to clarify, the reloadData method will need to be called on the UITableView object.
[myTableView reloadData];
From the documentation:
Reloads the rows and sections of the receiver.
- (void)reloadData
Discussion
Call this method to reload all the data that is used to construct the table, including cells, section headers and footers, index arrays, and so on. For efficiency, the table view redisplays only those rows that are visible. It adjusts offsets if the table shrinks as a result of the reload. The table view's delegate or data source calls this method when it wants the table view to completely reload its data. It should not be called in the methods that insert or delete rows, especially within an animation block implemented with calls to beginUpdates and endUpdates