UITableView willSelectRow method - uitableview

I have a tableView here, and its cell is a little bit different since I add a textField to the cell in order to input something, the UI looks like this:
while intantiating the cell, I use code like this:
[cell.contentView addSubview: myTextField];
Then, comes the problem:
in the willSelectRow method, I just write this:
- (NSIndexPath *)tableView:(UITableView *)tableView
willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
return nil;
}
But, in the built app, this row can still be highlighted because of a touch, it just soon recover when finger leaves the screen,
I mean, this cell will still turn to blue for a short moment, or in the debugger, it will become blue just before the willSelectRow method returns a nil.
can anyone help me find the problem?
Thanks a lot!

Guess you should also set the selection style to None in the GetCell override?

Related

Keep the color of text's cell when come back to table

I changed the color of text for the cell clicked in the table. But after the cell is clicked, when i come back to table the text of cell has the original color. Could you give me an advice?
This is the code in "didSelectRowAtIndexPath"
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.textLabel.highlightedTextColor = [UIColor blueColor];
Thank you
after the cell is clicked, when i come back to table the text of cell has the original color. Could you give me an advice?
You need to have the color for each cell stored somewhere other than in the table, so that you can reproduce the colors you want anytime the table redraws itself. Typically, you'll have some sort of data structure that stores the table's data, and that's usually the right place to save any changes the user makes. The table view's data source should have a -tableView:cellForRowAtIndexPath: method that sets the color according to what you've saved, along with any other cell attributes.
This is happen because the cells are reused, so lets say when you change text colour property of some cell it will be affected as you expect but when you scroll and that cell disappear off the screen it will be put to reuse pool and if it appears again on the screen table view takes some cell from the reuse pool but it's properties will be different so the colour won't persist.
You should keep somewhere, for example in NSMutableArray, info about which table was clicked.
You can add an index path to the array when you click the cell and in cellForRowAtIndexPath: check is this indexPath in the array and if it is change appropriate property.
The problem is that iOS throws away your cell if you scroll away and recreates it when it's needed (you scroll back to the cell).
If I were you, I would subclass UITableViewCell and overwrite
- (void)setSelected:(BOOL)selected animated:(BOOL)animated;
In there you would have
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected: selected animated: animated];
self.textLabel.textColor = selected ? [UIColor blueColor] : [UIColor blackColor];
}
Since iOS UITableView remembers which cell is selected, this should work fine, even when it's recreated.
The reason it's happening is what others are saying: cells are reused.
Storing selection state or color will work, however if you just need to make sure that selected cells have a different color for a label than non-selected cells, there's a way that does not require to use a supporting data structure.
You just need to check if the cell being setup at - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath is currently selected or not, and that can be achieved with [tableView indexPathForSelectedRow] if your table uses single selection, or [tableView indexPathsForSelectedRows] if it uses multiple selection.
The last case requires you to find the current indexPath in the returned array, and might be slower than using the supporting array.
But if the selection is simple, then this solution is probably faster, uses less memory and is easier to read (IMO).

userInteraction is enabled but button action isn't called

I am new to iOS programming. My cell is in a .nib. This cell displays an image which is working fine. I don't want the cell to perform any action or be selected. So, I have the following code :
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.contentView.userInteractionEnabled = YES;
My problem is I have a button which isn't called on touch. I have an action defined in the cell.m file. But nothing happens. I also tried adding the button programmatically, but in vain. I will appreciate any help or pointers as I have tried this for past few hours. I am pretty sure I am doing something silly.
Update:
This is how my cell xib structure looks -
There cell.nib, cell.m and cell.h. There is MainViewController which uses dequeueReusableCellWithIdentifier method to get the cell. This works fine as I am able to see the cell with the correct image. Action method is defined inside cell.m
Here is the xib file
https://www.dropbox.com/s/mzqzi6iz8lkbx2f/SHTableCell.xib
Thanks.
After checking the SHTableCell.xib you shared, it seems you have prevented user interaction on the cell itself so enabling user interaction on it's contentView / subViews will not make a difference.
In your xib, select "Test Cell" and check "User Interaction Enabled"
Also, it seems you haven't specified a re-use identifier to the cell.
It would be better if you specified one so that your -cellForRowAtIndexPath: could properly re-use the cell.
So... if you have something like:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//...
SHTableCell *cell = (SHTableCell*)[tableView dequeueReusableCellWithIdentifier:#"SomeIdentifier"];
//...
}
then, "SomeIdentifier" is what should be in the xib in the first place.

UITableViewCell being reused while still on-screen?

I have what probably seems like a really weird problem (it does to me!)
I am using a UITableView to display cells which each contain a UIWebView. I realise that this is a bad idea on the face of it, but I can't really do this any other way.
I am caching the heights of each cell when the UIWebView finishes loading, and then calling:
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:#[cellIndexPath]
withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
All of the germane code is in a Gist here.
I also have the UIWebViews cached in a dictionary on the data source, so it can be reused when the cell is reloaded.
This seems to sort of work, but I am encountering a lot of issues whereby the cells' contents will randomly disappear. I have added some logging into determine what's going on, and in what order, and it seems like some of the cells are being reused while they're still on-screen.
I see this in my logs while scrolling down:
2014-02-11 13:45:49.091 EApp[45936:70b] Generating cell for 1: Panning
2014-02-11 13:45:49.245 EApp[45936:70b] Generating cell for 2: Calibration
2014-02-11 13:45:50.063 EApp[45936:70b] Generating cell for 3: Aperture Priority
2014-02-11 13:45:50.063 EApp[45936:70b] Reusing cell: Stopping down
"Stopping down" in this case is a cell that is still on-screen. The "generating cell" items are logged inside the data source's cellForRowAtIndexPath and the "reusing" messages inside the cells' prepareForReuse.
Does anyone know what could be happening here? I know this seems complex.
The following line in your prepareForReuse is probably the culprit:
if ([self.contentWebView isDescendantOfView:self.contentWebView]) {
[self.contentWebView removeFromSuperview];
}
As the contentWebView is never a descendant of itself, it will not be removed from the cell, and the contentView will contain two webviews after the cellForRowAtIndexPath:
You probably meant to say:
if ([self.contentWebView isDescendantOfView:self.contentView]) {
[self.contentWebView removeFromSuperview];
}
Or simply:
[self.contentWebView removeFromSuperview];
One of the features/limitations of UITableView is that you don't know if, and can't depend on, a cell is being created or reused. You should always be able to handle both.
GENERALLY, when you call -reloadRowsAtIndexPaths:withRowAnimation:, you will get the cell from that indexPath to reuse. If that indexPath was on screen, it will be a cell that was on screen.
I don't know if it's the problem, but in the code you provided, you don't even initialize your cell...
I'm even surprise it works.
static NSString *CellIdentifier = #"FeedItemCell";
EFeedItemCell *cell = [self.tableViewController.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
you should add to it :
if (!cell) {
cell = [EfeedItemCell alloc] initWithReus....];
}
From your code it seems that you are caching the webViews and then are adding them to cells programmatically. This can create random problems similar to what I had faced in the passed.
You must use EFeedItemCellWebView in your storyboard. Just add a UIWebView and change the class name to your custom class. And then when the data is loaded just simply change its contents in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

Prototype Cell not being used by tableview

I have read many posts about similar problems but nothing seems to work, I am obviously doing something wrong. I have a TableViewController that is in a StoryBoard (XCode 5). For the PrototypeCell I set the type to custom and set the Identifier to "pbvcell". I added some labels, changed the background etc.. Here is my tableview delegate method for setting the cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"pbvcell"];
// Configure the cell...
PBVlead *lead = [self.leads objectAtIndex:indexPath.row];
NSLog(#"Cell class %#", [cell class]);
UILabel *leadNameLabel = (UILabel *)[cell viewWithTag:1];
leadNameLabel.text = lead.leadName;
return cell;
}
Now the app launches but even after I add an object to the tableview datasource array and do a reload data, the cells are blank, like the custom cell is not being used. It looks like this should be easy and thats all I need to do. What on earth am I missing?
I left this in a comment above but just to keep things tidy I will post it as an answer here. It is silly but it is good to note that you have to manipulate the contextView of a prototype cell and not the tableview cell itself in order for your visual changes to have an effect...
"Because I embrace my own stupidity I will tell everyone what was going on here. I had set the TableCell background to blue and added some UILabels and set there color to white to show up against the blue background. Run the app, no labels.... What I finally realized is, I had not set the Content View background to blue. So..... What was happening was the labels actually are shown in the content view in the view hierarchy. White labels on a white background equals, invisible... :-) I set the content view background to blue and wola, there is everything! :-) Brother..?

Manage Swapping between two cells rather than changing the NSIndexpath of other UITableViewcells

I know it's the default property of rearrangement of tableviewcells when UITableView is in editing mode & user just reorder the Rows which is handled by UITableViewController.
As per Apple Doc : Reordering of Rows
Now what I want to do is, when I drag the cell over other cells, the backend cells should not get rearranged automatically, just the cell on which I drop the dragged cell should gets rearranged, a kind of Swapping between two cells.
For better understanding, please refer the below image. I should be able to Shift Jones to Room1 & the tableview controller should able to automatically be shifting Smith2 to Room3.
Below are delegates methods which I am using :
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
NSString *temp = [roomstoringArray objectAtIndex:sourceIndexPath.row];
[roomstoringArray removeObjectAtIndex:sourceIndexPath.row];
[roomstoringArray insertObject:temp atIndex:destinationIndexPath.row];
// [temp release];
}
Problem is :
How can I stop other cells to get rearranged automatically while I
am dragging the cells over other.
There none of the delegate method which gets called when one used to
Drag the cell over others, only method called is
moveRowAtIndexPath when one drop the cell on it. So, even can't check for some condition & didn't find any scope of this enhancement
within existing TableView.
Is there any property with the TableView where I can stop such kind of behavior to perform the swapping between two cells only where rest of rows remain at the same indexPath.Alos, can someone please help me out with some-other way,if any.
For Problem you mention, Please check UITableView Delegates from here.
Below methods are helpful to you.
targetIndexPathForMoveFromRowAtIndexPath
canMoveRowAtIndexPath
For Swap b/w two rows you can get idea by this answer.

Resources