Selection in TableViewCell - objective-c

On selection of tableviewcell, i am change color of tableviewcell.
when i select cell on tableViewCell and scroll some other cell also selected.
after scroll the other cell also affected
this is my code
static NSString *identifier = #"TBDCreateGamePlayerCell";
TBDCreateGamePlayerCell *playerCell = (TBDCreateGamePlayerCell *)[tableView dequeueReusableCellWithIdentifier:#"TBDCreateGamePlayerCell"];
if (!playerCell) {
NSLog(#"creating a new cell : %d",row);
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TBDCreateGamePlayerCell" owner:nil options:nil];
playerCell = [nib objectAtIndex:0];
}

You must implement this delegate method:
- (void)tableView:(UITableView *)tableView
willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
Inside this method change the cell background back to the default color.
From the Apple Docs:
Discussion
A table view sends this message to its delegate just before
it uses cell to draw a row, thereby permitting the delegate to
customize the cell object before it is displayed. This method gives
the delegate a chance to override state-based properties set earlier
by the table view, such as selection and background color. After the
delegate returns, the table view sets only the alpha and frame
properties, and then only when animating rows as they slide in or out.

Look at the code below...
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selected_index= indexPath.row;
[tableView reloadData];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.accessoryType=UITableViewCellAccessoryNone;
for (UIView *view in cell.contentView.subviews) {
[view removeFromSuperview];
}
if(indexPath.row==selected_index)
{
cell.contentView.backgroundColor = [UIColor whiteColor];
}
else
{
cell.contentView.backgroundColor = [UIColor clearColor];
}
}

Related

UITableViewCell : initWithFrame : reuseIdentifier deprecated

I'm having trouble with creating my UITableViewCell since UITableViewCell : initWithFrame : reuseIdentifier is deprecated. Please stay with me, I've looked over other questions about this but couldn't find them helpful. So here is my function.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCellObject *cell = (MyCellObject *)[tableView_ dequeueReusableCellWithIdentifier:#"cellid"];
if (cell == nil) {
cell = [[[ChatCell alloc] initWithFrame:CGRectZero reuseIdentifier:#"cellid"] autorelease];
}
return cell;
}
As I read from other questions, I tried:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCellObject *cell = (MyCellObject *)[tableView_ dequeueReusableCellWithIdentifier:#"cellid"];
if (cell == nil) {
cell = [[[MyCellObject alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cellid"] autorelease];
}
return cell;
}
But my cell won't display its text then. I can tap the cell row and it becomes selects, but no visible text. Because my cell text is handled in my MyCellObject and not cell.textLabel.text, I need to init the cell with a frame (initWithFrame), but I also need to init it with an identifier (reuseIdentifier).
Thanks!
EDIT: I don't think MyCellObject as everything worked before the above function was deprecated. Here's part of MyCellObject and it is derived from UITableViewCell:
- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier];
if (self == nil) {
return nil;
}
tagLabel = [[UILabel alloc] initWithFrame:CGRectZero];
tagLabel.backgroundColor = [UIColor clearColor];
tagLabel.font = [UIFont systemFontOfSize:14];
tagLabel.lineBreakMode = UILineBreakModeWordWrap;
tagLabel.opaque = YES;
[self addSubview:tagLabel];
}
The reason I have it setup that was is so I can "micro manage" the text in it a little more.
1) You haven't set the cell title. So you won't see any text on the cell. Here you have used a UITableViewCell class. So you will need to add a label to the cell in the storyboard and set outlet to UITableViewCell in your case which is MyCellObject class. Then you will be able to set text to that label.
2) You can just use
MyCellObject *cell = (MyCellObject *)[tableView dequeueReusableCellWithIdentifier:#"cellid"];
Try this..
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCellObject *cell = (MyCellObject *)[tableView dequeueReusableCellWithIdentifier:#"cellid"];
cell.myCustomLabel.text = #"Your text";
return cell;
}

How to use a subclassed cell from the IB without reusing it again?

I've created a cell with 2 UIButtons in the IB and subclassed it. How can I use it without reusing it over again? (for a small fixed table)
I tried doing something like:
RaffleResultCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
but that won't show my cell in the UITableView, just a blank one.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//Where we configure the cell in each row
id currentRaffle = [_winnings objectAtIndex:indexPath.row];
RaffleResultCell *cell = [tableView dequeueReusableCellWithIdentifier:#"raffleResCell"];
if (cell == nil) {
cell = [[RaffleResultCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"raffleResCell"];
}
return cell;
}
It is not a good practice to avoid Reusability,I will say dont do it
Reusability is done in this line
RaffleResultCell *cell = [tableView dequeueReusableCellWithIdentifier:#"raffleResCell"];
Remove that line and just call alloc method everytime without the check loop
Like
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
id currentRaffle = [_winnings objectAtIndex:indexPath.row];
cell = [[RaffleResultCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"raffleResCell"];
return cell;
}
You told you set up the UITableViewCell in IB then you need to get Nib file and then use that file as
// Get nib file from mainBundle
NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"RaffleResultCell" owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[UITableViewCell class]]) {
RaffleResultCell *cell = (RaffleResultCell *)currentObject;
break;
}
}
now setup any text for your button and return cell

How to directly edit a row in a UITableView, without entering in Editing Mode

In a UITableView, I would like to be able to edit the cell.textLabel.text property of the row, when such row is touched.
In other terms, I would like to be able to edit the row directly touching it, instead of entering into edit mode.
How can I implement this?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
CMTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CMTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
int tagsCount = [[currentComic Tags] count];
[[cell textField] setTag:[indexPath row]];
[[cell textField] setText:[tagsDisplayName objectAtIndex:[indexPath row]]];
return cell;
}
And this is the subclass CMTableViewCell:
...
-(void)viewDidLoad
{
textField = [[UITextField alloc] init];
[textField setFrame:CGRectMake(5,5,50,400)];
[self addSubview:textField];
}
Add UITextField without borders as subview. Before adding it to subview - set Tag nubmer to UITextField from indexPath.row at tableview cellForRowAtIndexPath method. When user entered data - save it with UITextFieldDelegate methods when "Return" button was pressed. Unfortunately I can't give you code, because right now I'm on Windows. Home this will help
UPDATE: Tag number needed to change data in your DataSource. When you pressed "Return" button in your UITextField, you can save changed by getting UITableViewCell by this tag number from UITextField.
It's simple:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.textLabel.text = #"...";
}
UPDATE
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITextField *textField = [[UITextField alloc] init];
[textField setTag:[indexPath row]];
[tagsTableView addSubview:textField];
FreeAndNil(textField);
}

UITableViewCells are out of order

Okay, I am having another UITableView problem. For some reason the indexPath.row is all jumbled up. When I comment out the if statement that sets up the cell, everything works fine. The NSLogs tell me that they are loading in order, but all the cells are out of order.
It also seems as if they repeat; I only see 8 cells, and they repeat over and over.
Here's my code:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
NSLog(#"row: %d",indexPath.row);
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.backgroundColor = [UIColor clearColor];
cell.contentView.backgroundColor = [UIColor clearColor];
// Add subviews like this:
// [[cell contentView] addSubview:objectName];
// And I get the row number like this: indexPath.row when getting objects from the array
}
return cell;
}
To use your code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
NSLog(#"row: %d",indexPath.row);
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.backgroundColor = [UIColor clearColor];
cell.contentView.backgroundColor = [UIColor clearColor];
// Add subviews like this:
// [[cell contentView] addSubview:objectName];
}
### Move this here ###
// And I get the row number like this: indexPath.row when getting objects from the array
return cell;
}
" I only see 8 cells, and they repeat over and over." Correct.
What your missing is that that is how it is supposed to work. That's why only if the cell is nil are you alloc & init'ing a new cell. So you alloc and init and set the colors and add subviews in the if statement. Then after the if(cell==nil) you know you have a valid cell to populate with some data according to the indexPath variable passed in.
The problem is that now you are setting up the cell when it is nil and assigning all of the displayed data according to the indexPath passed in. The problem is cell is not nil the second time it's used so the data is never changed.
To address your speed comment further, I'll use an old fallback example.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
UILabel *hugeLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, cell.frame.size.width, cell.frame.size.height)];
hugeLabel.tag = 300;
[cell addSubview:hugeLabel];
}
[(UILabel *)[cell viewWithTag:300] setText:[arrayOfStrings objectAtIndex:indexPath.row]];
return cell;
}
If you look at the sample above, you'll see that we add a UILabel to the cell setting it's tag to 300. Then after the if statement we will have either a brand new cell or a reused cell with text already in the label. No matter either way we simply change the text of the existing label to whatever it should be considering the row. In this way we avoid creating views over and over.
If you are dead-set on caching your UITableViewCells you could do so like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row < _cells.count){
return [_cells objectAtIndex:indexPath.row]; // _cells is an NSMutableArray setup in viewDidLoad
}
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#""];
cell.textLabel.text = [source objectAtIndex:indexPath.row]; // source is an NSArray of NSStrings I set up in viewDidLoad
[_cells addObject:cell];
return cell;
}
Note When running this on device don't be surprised when in the console you see Received memory warning What's efficient & what's easy are often not the same.
The way you have it set up now, cell.selectionStyle, cell.backgroundColor, and cell.contentView.backgrounColor, etc., only get set when if (cell == nil) is true. You need to move that code outside the if statement block, so that it gets called both when dequeueReusableCellWithIdentifier: produces a cell and when it has no cells in inventory and produces nothing (i.e., nil).

When I used layoutSubviews method of UItableViewcell with category in my file,something disappeared

when I used layoutSubviews method of UItableViewcell with category, just like the code below
#implementation UITableViewCell (forimage)
- (void)layoutSubviews{
[super layoutSubviews];
self.imageView.frame = CGRectMake(0, 0, 50, 50);
}
#end
when I used the code below to draw the cells , the textLabel was disappeared ,anyone know why it be that~, and does that mean if I use layoutSubviews,I must write all the subviews what I need in the method?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
RadioInfo *radioinfo = [radios objectAtIndex:indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:#"%#",radioinfo._name];
if(!radioinfo._logo){
if(self.tableView.dragging == NO && self.tableView.decelerating == NO){
[self startPicDownload:radioinfo forIndexPath:indexPath];
}
cell.imageView.image = [UIImage imageNamed:#"1.jpg"];
}
else {
cell.imageView.image = radioinfo._logo;
}
return cell;
}
What you want to do is add to the behaviour of UITableViewCell's layoutSubviews method, not replace it.
To properly add to the behaviour, subclass the cell and perform your own layout, as you have above but add a [super layoutSubviews] right at the top of your method to ensure that the cell's own basic layout is performed first.