UITableViewCell Loses Properties After Deselection - iphone

I have a custom subclass of UITableViewController that uses a set of custom subclass of UITableViewCells.
There is nothing too fancy. The table cell's have two subviews in their content view.
Right now I have the user select a cell, a navigation controller pushes to a color selection screen. The user selects a color. Great. The table view is a delegate of this view. It receives the color, updates the selected cell so that the subview now uses this background color, and then pops the current view from the navigation controller.
It all works! The tableViewController slides back into view and the indicator in the cell now displays the background color the user selected. BUT after the table view appears, the cell selected cell gets a blue highlight applied to it automatically. This is some built in magic from the TableViewController. It's nice but it's resetting my cell's indicator status.
Problem is, I can't find out where to properly update the cell to this new color. The color is stored as an ivar in the tableViewController. So I thought trying this out at:
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
But alas this method doesn't fire as a result of the magic UIKit is doing to briefly highlight the cell. Any ideas where I need to update my cell properly?

I'm not sure how you are setting the background color yet, but you should be using the backgroundView property of your UITableViewCell subclass.
someCell.backgroundView.backgroundColor = someColor;
(from inside your UITableViewController, or wherever you are getting that color information back from your picker).
Doing this should not reset the background color when the cell goes from selected to deselected.

Related

Woes with the selected button state in custom UITableViewCells

I have a custom UITableViewCell with two buttons in it, mycell.m/mycell.h/mycell.xib. In the XIB I have given the buttons a sample label, and I change that text in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *).
Now, when I click the buttons, while I'm holding my finger on it, it will show the sample text instead of the actual text. And should I miss the button and touch inside the custom UITableViewCell, both buttons change text to the sample text, and they don't redisplay the text I set in cellForRowAtIndexPath until I scroll the cell off-screen and back again.
Any clues to what I might be doing wrong? I haven't found any way to set a selected text.
Cheers
Nik
Well, trying again...
I set up a mini project and recreated the problem. After puzzling over why the text I set wasn't being used, I finally realized that you can set a different title for every control state (setTitle:forState:). Normally, if you just set titleLabel.text, then you're setting it for UIControlStateNormal, which is then used by default for all other states. However, IB apparently sets the sample title you specify for all the states separately, not just for normal state. So in your code, you're indirectly doing a setTitle:forState:UIControlStateNormal, but the titles set by IB for all the other states are remaining unchanged. So when you hold down the button (UIControlStateSelect) or you hit the cell (UIControlStateHighlight), then the sample label is displayed. SO...either remove the sample label in IBuilder (the easy path), OR set the label for all the relevant states.
Old incorrect answer:
cellForRowAtIndexPath is only called when the tableView needs to display a cell (e.g. when scrolling back onto the screen.) It's not called anytime a cell is on the screen. Sounds like you've got another routine (e.g. buttonPressed) that's set up as an IBAction from the buttons.

Clarify undocumented behavior of UITableViewCell on highlight event

UITableViewCell modifies the contents of it's contentView hierarchy when the cell is is highlighted (user touches down on the cell).
Two examples I've found to date:
Put a UIView in a cell's contentView with a background color. That UIView's background color is removed when the table cell is highlighted (it's apparently set to have a clear background.)
Put a UIButton in contentView. When the cell is highlighted, the button is also forced into the highlighted state.
It's as if there's some logic in the UITableView cell that inspects all views in the cell's hierarchy and modifies them according to a set of mysterious rules, then restores them back to normal once the cell is un-highlighted.
Can anyone explain what and why UITableViewCell is modifying (unexpectedly and in an undocumented fashion) in the contents of my custom table view cells?
Thanks!
The highlighting of the UITableViewCell is documented in the Apple docs as follows:
The highlighting affects the
appearance of labels, image, and
background. When the the highlighted
state of a cell is set to YES, labels
are drawn in their highlighted text
color (default is white). The default
value is is NO. If you set the
highlighted state to YES through this
property, the transition to the new
state appearance is not animated. For
animated highlighted-state
transitions, see the
setHighlighted:animated: method.
Note that for highlighting to work
properly, you must fetch the cell’s
labels using the textLabel and
detailTextLabel properties and set
each label’s highlightedTextColor
property; for images, get the cell’s
image using the imageView property and
set the UIImageView object’s
highlightedImage property.
This does not mention UIButtons, but this post is about how to prevent the button from going into the highlighted state when the cell does.

UITableViewCell subview (left side)

Is it possible to implement a subview of a UITableViewCell on the left side of the cell that crossfades when the table enters the editing mode?
Another problem I face is that the bounds of the cell.textLabel are read-only. Is it possible to use some sort of inset for that label? (Because I, like mentioned above, want to use a View on the left side)
Edit: How do I perform an action (in this case fade a subview) when the whole table enters editingmode? (Not through a swipe over a cell). The reason why I want to implement this is because the tableview shows the "-" button on the left side of the cells if it is in editingmode. (I want to show my own button on the left side of the cells if editing=NO, fade it out if editing=YES and show it again if the tableView leaves editingmode (editing=NO))
A first thought directs me to something like this:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
if(editing) {
//fade out my own button
} else {
//show my own button
}
}
But I would have to loop through all the cells and I think this leads to a substantial performance worsening. What do you think?
You want to set the Editing Accessory View of a UITableViewCell. See the editingAccessoryView property for information on this. More information can be found in the Customizing Cells section of the TableView Programming Guide.
The label within the content view of a table view cell is read-only so you can not reassign it but its properties are mutable. You can actually move the label around within the bounds of the table view cell. It's probably confusing to grasp, but have a look at the Characteristics of Cell Objects section of the Table View Programming Guide. In it, the bounding boxes for each of the nested views are shown (not all of them are always visible). For your purposes, a good exercise would be to set the background color of each subview of a UITableViewCell to a different color and then try to adjust the sizes of them. Doing so and understanding what's going on will probably let you achieve the end-result that you desire.
In the end I created a custom UILabel that I used instead of the default UITableView textLabel and added a custom button on the left side. In the setEditing method I fade this button in/out.

Bring UIScrollView to foreground

I have a UIScrollView inside a cell but when the cell is selected the view disappears in the background how can I put it back to foreground. Thanks
JVPython
It's possible you aren't properly setting up your UITableViewCell so that selection doesn't cover up the cell contents. Perhaps you are adding the scrollview to the cell directly and not to the contentView of the cell?
The Apple documentation describes the layout of a cell and what happens to those elements when a cell is selected: Table View Programming Guide
Have you tried:
[self.view bringSubviewToFront:myScrollerView];

Drawing selected state on custom UITableViewCell

I have a customer UITableViewCell whose whole display is drawn indrawRect. When it draws it creates CGLayers so that it can reuse certain pieces when something is changed.
I have changed my UITableViewCellSelectionStyle to "None" because I don't want the default selected view to cover my drawing.
My problem is that I call setNeedsDisplay in setSelected:animated: for my cell but by the time drawRect is called, setSelected:animated: has already been called again to deselect the cell. In my table view controller didSelectRowAtIndexPath, I call deselectRowAtIndexPath as Apple advises.
EDIT - I have also tried called the setNeedsDisplay on my cell from my table view controller's (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath but that didn't change anything.
Any ideas? Thanks.
Use the table cell's selectedBackgroundView property. If you assign a custom view to that, it'll get shown and hidden at the same time as the default selection backgrounds—in other words, without having to wait for the setNeedsDisplay to get around to calling drawRect: on the cell itself.