Activate cell's accessory view (UISwitch) when didSelectRowAtIndexPath is called - objective-c

Every cell of my tableView has a UISwitch as an accessoryView:
UISwitch *mySwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
cell.accessoryView = mySwitch;
[mySwitch addTarget:self action:#selector(SwitchToggle:) forControlEvents:UIControlEventValueChanged];
Switch is toggled when the user taps it, but I also want it toggled when the didSelectRowAtIndexPath is called (when the user taps on that cell).
I tried this (but it doesn't work):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UISwitch *tempSwitch = (UISwitch *)[tableView cellForRowAtIndexPath:indexPath].accessoryView;
[tempSwitch addTarget:self action:#selector(SwitchToggle:) forControlEvents:UIControlEventValueChanged];
[tableView deselectRowAtIndexPath:indexPath animated:YES]; // cell selection fadeout animation
}
Thanks.

The code must look like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UISwitch *tempSwitch = (UISwitch *)[tableView cellForRowAtIndexPath:indexPath].accessoryView;
[tempSwitch setOn:!tempSwitch.on animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Remember that you also have to update your model.

Related

How to add a content view on UITAbleViewCell when a row is selected?

I'm trying to add a button when a row is selected in UITableView and also remove it when row is tapped second time, i don't want custom UITableViewCell.
Any suggestion or sample code will be appreciated.
code i've tried:
in cellForRowAtIndexPath method
if(cell.selected == YES){
UITextField* numOfBottles =[[UITextField alloc] initWithFrame:CGRectMake(240,9.0f,50, 25)];
numOfBottles.tag = indexPath.row;
[numOfBottles setBorderStyle:UITextBorderStyleNone];
[numOfBottles setBackgroundColor:[UIColor clearColor]];
[numOfBottles setTextColor:[UIColor whiteColor]];
[numOfBottles setTextAlignment:UITextAlignmentLeft];
[numOfBottles setBackground:[UIImage imageNamed:#"blue_dropdown_normal.png"]];
[numOfBottles setFont:[UIFont systemFontOfSize:16.0f]];
[numOfBottles setDelegate:self];
NSString* quantity = [[NSString alloc] initWithString:[subtotalObj.qtyArray objectAtIndex:(indexPath.row - 1)]];
[numOfBottles setText:quantity];
[numOfBottles setTextAlignment:UITextAlignmentCenter];
[numOfBottles setBackgroundColor:[UIColor whiteColor]];
numOfBottles.keyboardType = UIKeyboardTypeDefault;
// numOfBottles.tag = indexPath.row;
[cell.contentView addSubview:numOfBottles];
[numOfBottles release];
}
and in didSelectRowAtIndexPath method
[tableView reloadData];
But still button(textfield with background image) is not rendered.
I think the best way is to use a UITableViewCell subclass.
But you can use my answer on another question to make your TableView rerender and place a button in your cell.
- (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];
}
if(indexPath.row == selectedRow){ // if your criteria where met
//add your button
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//do your select things here
selectedRow = indexPath.row; //where selectedRow is a class variable
[self.tableView reloadData]; // rerenders the tableview
}
There's UITableView delegate, - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath implement it, where you'll get the row which user tapped, get the current cellusing cellForRowAtIndexPath: you need to pass NSIndexPath using the section and row. Now check if cell.contentView subviews has UIButton which you want? If yes, perform removeFromSuperView else addSubView. If you cell have already filled with UIButtons you can give unique tag to distinguish them.
Use these delegates
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = (UITableViewCell*)[tableView cellForRowAtIndexPath:indexPath];
//Create reference of button with tag 999
cell.contentView addSubView:yourButtonReference]
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = (UITableViewCell*)[tableView cellForRowAtIndexPath:indexPath];
UIButton *btnAdded = (UIButton *)[cell viewWithTag:999];
if(btnAdded){
[btnAdded removeFromSuperView];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
}

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);
}

UITableViewCell configuration

I have a UITableView in my app, which stores a list of URLs. Above table there are UITextField and UIButton.
When user types some URL on textField and then presses the button I add those URL like the top element in the tableView.
Next, when user selects any of URLs, I want to create a button within selected UITableViewCell to let user to follow that URL (actually, it's not important). Here's didSelectRowAtIndexPath method definition:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.recentUrlsTableView cellForRowAtIndexPath:indexPath];
UIButton *button = [UIButton new];
button.frame = CGRectMake(cell.frame.size.width - 34, cell.frame.origin.y + 10, 24, 24);
button.backgroundColor = [UIColor lightGrayColor];
[button setTitle:#">" forState:UIControlStateNormal];
[cell.contentView addSubview:button];
[button release];
}
But I want those button to disappear when I deselect cell. So, I tried this thing (I kow it looks stupid, but unfortunately I didn't know better way to find my button in there):
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.recentUrlsTableView cellForRowAtIndexPath:indexPath];
for (UIView *subview in cell.subviews)
{
if ([subview isKindOfClass:[UIButton class]])
if ([[(UIButton*)subview titleLabel].text isEqualToString:#">"])
{
[subview removeFromSuperview];
[subview release];
}
}
}
But this stuff seemed to work incorrectly - instead of releasing and disappearing at all, button started to in another rows - even those, which were empty.
After that I tried to do same actions for every row in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method. But it also didn't help.
I guess, that there are some trivial issue, but I can't find it. So, I will highly appreciate any of your help!
When you scroll up/down the table cells get reused and cell (with button) can be populated with completely diffetent contents (i.e. is used for different indexpath). That's why you're experiencing this.
So there is always only one button (or none) on your table.
You'd be best off if you create (reatin & keep reference of it) one button from outside the table. Your didDeselectRowAtIndexPath would then look like:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.recentUrlsTableView cellForRowAtIndexPath:indexPath];
//you have outside reference for this button
[button removeFromSuperView];
button.frame = CGRectMake(cell.frame.size.width - 34, cell.frame.origin.y + 10, 24, 24);
[cell.contentView addSubview:button];
}
If this doesn't work you should use combination of reloadData and cellForIndexPath. Like so:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.recentUrlsTableView reloadData];
}
- (void)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//create your cell as usually
if ([cell isSelected]) { //i'm not sure if this is the right way to detect selected cell
[button removeFromSuperView];
button.frame = CGRectMake(cell.frame.size.width - 34, cell.frame.origin.y + 10, 24, 24);
[cell.contentView addSubview:button];
}
}

UIView background color does not take effect

Can someone tell me why this is not working right?
I have these lines of code below within my table view cell for tableView:didSelectAtIndexRowPath: method.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[[tableView viewWithTag:199]removeFromSuperview];
CGSize cellSize = [tableView cellForRowAtIndexPath:indexPath].frame.size;
UIView *subSelectionView = [[UIView alloc]initWithFrame:CGRectMake(10, 0, (int)cellSize.width - 20, 100)];
[subSelectionView setBackgroundColor:[UIColor blueColor]];
subSelectionView.layer.borderColor = [UIColor grayColor].CGColor;
subSelectionView.layer.borderWidth = 1;
subSelectionView.tag = 199;
[[tableView cellForRowAtIndexPath:indexPath]addSubview:subSelectionView];
}
Notice the code:
[subSelectionView setBackgroundColor:[UIColor blueColor]];
Obviously, I want to change the color of the subview that I added to the UITableViewCell but why is it not working ?
jus reload the table after adding the subview on the table
[[tableView cellForRowAtIndexPath:indexPath]addSubview:subSelectionView];
[tableview reloadData];
Add the following line to the start of the method
[tableView deselectRowAtIndexPath:indexPath animated:NO];
So ur method would be
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
[[tableView viewWithTag:199]removeFromSuperview];
....
}

UITextField unable to become first responder if added to UITableViewCell via accessoryView

Like many other users, I'm trying to set throw a UITextField into a UITableViewCell to be used for editing a row. But instead of adding a new view, I'm trying to use the accessoryView property. At first I tried this...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITextField *textField =[[UITextField alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 200.0f, 44.0f)];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryView = textField;
[textField becomeFirstResponder];
}
...and the UITextField is added properly, but I need to tap it again to get the keyboard to show. However if I do this...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITextField *textField =[[UITextField alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 200.0f, 44.0f)];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[cell addSubview:textField];
[textField becomeFirstResponder];
}
...it works, the keyboard shows up but, I don't get any of the other benefits of having it as the accessoryView (easier positioning with other views moving around it). I suppose the addSubview: call is altering the responder chain or something and allowing my UITextField to become the first responder, but thought maybe there was another way to do this allowing me to set the cell's accessoryView instead. Thanks.
I hate my solution, but it works and am up for a better way.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
CGRect detailTextLabelFrame = cell.detailTextLabel.frame;
detailTextLabelFrame.origin.x -= 100.0f;
detailTextLabelFrame.size.width += 100.0f;
UITextField *textField = [[UITextField alloc] initWithFrame:detailTextLabelFrame];
cell.detailTextLabel.hidden = YES;
cell.accessoryView = textField;
// These are the two lines that made it work, but it feels ugly
[cell.accessoryView removeFromSuperview];
[cell addSubview:cell.accessoryView];
[cell.accessoryView becomeFirstResponder];
}
I hope you know about textfield delegate.Try this way....may be it will help you.
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
if(theTextField == yourtextfieldname) {
[yourtextfieldname resignFirstResponder];
}
return YES;
}