I have a label and textfield in tableview, now what I want is whatever value I insert in textfield in textfieldDidEditing method it should calculate the value and return it to the label in that indexpath for tablevievw.
In textfieldDidEditing, you can get the cell of the corresponding textfield, calculate value and assign it to label as follows:
yourTableViewCell *cell = (yourTableViewCell *)[[textField superview] superview];
cell.yourLabel.text = value;
/* u just give Tag to TextField and in textFieldDidEndEditing, save textfield text into an string and then reload the row...here is the code..also have sample */
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexpath
{
UITableViewCell *cell = [[UITableViewCell alloc] init];
UITextField *txtField1 = [[UITextField alloc]initWithFrame:CGRectMake(20, 10, 100, 80)];
txtField1.tag = indexpath.row;
txtField1.delegate= self;
[cell addSubview:txtField1];
UILabel *label1 = [[UILabel alloc] initWithFrame:CGRectMake(140, 10, 100, 80)];
[cell addSubview:label1];
//set text in label ** str1 comes from textFieldDidEndEditing
label1.text = str1;
return cell;
}
-(void)textFieldDidEndEditing:(UITextField *)textField
{
//save textField text to any string**declair it global
str1 = textField.text;
//reload selected row in table
NSIndexPath *durPath = [NSIndexPath indexPathForRow:textField.tag inSection:0];
NSArray *paths = [NSArray arrayWithObject:durPath];
[tbl reloadRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationRight];
}
Related
I'm working on an iPhone app that parses an XML file into a UITableView. It lists all of the titles of items within the XML file, and I'm trying to have the cell expand and add the body content of the selected item when a specified cell is selected.
I can get the cell to expand correctly, but when I have had no luck adding the body content as a subview. When populating the cell at cellForRowAtIndexPath I can add the body content and it displays fine.
My question is, how do I add a subview to the selected cell after it has been selected?
My cellForRowAtIndexPath function, with the 'functioning' bodyLabel commented out:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"Cell";
issue *curIssue = [[parser issues] objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];
CGRect nameFrame = CGRectMake(0,2,300,15);
UILabel *nameLabel = [[UILabel alloc] initWithFrame:nameFrame];
nameLabel.tag = 1;
nameLabel.font = [UIFont boldSystemFontOfSize:12];
[cell.contentView addSubview:nameLabel];
CGRect bodyFrame = CGRectMake(0,16,300,60);
UILabel *bodyLabel = [[UILabel alloc] initWithFrame:bodyFrame];
bodyLabel.tag = 2;
bodyLabel.numberOfLines = 10;
bodyLabel.font = [UIFont systemFontOfSize:10];
bodyLabel.hidden = YES;
[cell.contentView addSubview:bodyLabel];
}
UILabel *nameLabel = (UILabel *)[cell.contentView viewWithTag:1];
nameLabel.text = [curIssue name];
UILabel *bodyLabel = (UILabel *)[cell.contentView viewWithTag:2];
bodyLabel.text = [curIssue body];
return cell;
}
Here is my heightForRowAtIndexPath function, where I'm trying to add the subview. When trying to execute, I receive a EXC_BAD_ACESS exception when trying to alloc the *bodyLabel element.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger defCellHeight = 15;
NSInteger heightModifier = 10;
if([self cellIsSelected:indexPath]){
return defCellHeight * heightModifier;
}
return defCellHeight;
}
My didSelectRowAtIndexPath function, which allows the cell to grow/shrink:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
BOOL isSeld = ![self cellIsSelected:indexPath];
NSNumber *seldIndex = [NSNumber numberWithBool:isSeld];
[selectedIndexes setObject:seldIndex forKey:indexPath];
UILabel *label = (UILabel *)[tableView viewWithTag:2];
label.hidden = NO;
[curIssView beginUpdates];
[curIssView endUpdates];
}
And finally, the cellIsSelected helper function which returns true if the cell is selected:
-(bool) cellIsSelected:(NSIndexPath *)indexPath
{
NSNumber *selIndex = [selectedIndexes objectForKey:indexPath];
return selIndex == nil ? FALSE : [selIndex boolValue];
}
You can find the full source file here.
Seems like you're allocating and adding the same UILabel's multiple times. You should only have to do it once within the cellForRowAtIndexPath method. You might also want to set the bodyLabel to hidden in the cellForRowAtIndexPath method, then set it to not hidden when the cell has been selected. With something like:
bodyLabel.hidden = YES;
Another thing. Why are you deselecting the row within the didSelectRowAtIndexPath?
Why are you creating a UILabel in heightForRowAtIndexPath?
If you're trying to add it to the row, use the cellForRowAtIndexPath method you used above.
Simply adding a subview to the UITableViewCell or anywhere else in view with UIView's addSubview method inside of didSelectRowAtIndexPath will work for displaying a subview when a UITableView row is selected.
To add a subview to the cell when you select it, it's pretty straightforward:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
/*
.. your other setup
*/
UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
[cell.contentView addSubview:<your subview>];
}
I'm trying to add a UITextField as a subview to my table cells. The content of the text fields is fine until I start scrolling and the cells start to be reused. The images illustrate the problem.
At first, the blue values on the right in the UITextField are correct, i.e. the value corresponds to the row number. The second and third images, scrolled down and back up, show that the values are being reused in odd ways.
How do I avoid this? Using unique values for reuseIdentifier solves this problem, but obviously it's not very efficient.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITextField *numberTextField;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
numberTextField = [[UITextField alloc] initWithFrame:CGRectMake(200, 10, 95, 30)];
numberTextField.adjustsFontSizeToFitWidth = YES;
numberTextField.textColor = [UIColor blueColor];
numberTextField.placeholder = #"Enter value";
numberTextField.keyboardType = UIKeyboardTypeDecimalPad;
numberTextField.tag = ([indexPath row]+1);
numberTextField.backgroundColor = [cell backgroundColor];
numberTextField.textAlignment = NSTextAlignmentRight;
numberTextField.clearButtonMode = UITextFieldViewModeNever;
numberTextField.clearsOnBeginEditing = YES;
[numberTextField setEnabled:YES];
[cell addSubview:numberTextField];
} else {
numberTextField = (UITextField *)[cell.contentView viewWithTag:([indexPath row]+1)];
}
cell.textLabel.text = [NSString stringWithFormat:#"Row %i",[indexPath row]+1];
numberTextField.text = [NSString stringWithFormat:#"Value: %i",[indexPath row]+1];
return cell;
}
The problem is you only assign the tag to the numberTextField when it is created. If it gets reused, it doesn't get its tag reassigned.
You should use a constant tag number for the UITextField instead of using row+1.
How can i add textfield in tableview cell (on each row).
This textfield will be in middle of each row.
And also set Tag on each textfield of cell to access their text.
Of course you can, a small example:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"test"];
if(cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"test"] autorelease];
UITextView *tv = [[UITextView alloc] initWithFrame:CGRectMake(0, (cell.contentView.bounds.size.height-30)/2, cell.contentView.bounds.size.width, 30)];
[cell.contentView addSubview:tv];
[tv setDelegate:self];
tv.tag = indexPath.row;
}
return cell;
}
...
- (void)textViewDidEndEditing:(UITextView *)textView {
NSLog(#"%d", textView.tag);
[textView resignFirstResponder];
}
...
I have a tableview with four sections and all of the sections have two textfields and a label in different rows. I have added some text as placeholder of textfield. Initially the data appears fine but when I scroll the tableview the cell starts to have overlapped data.
My Code:
- (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];
}
if(indexPath.row==0) {
UITextField *txtName = [[UITextField alloc] initWithFrame:CGRectMake(5, 5, 300, 30)];
txtName.placeholder = #"Full Name";
[cell.contentView addSubview:txtName];
[txtName release];
}
else if(indexPath.row==1) {
UITextField *txtEmail = [[UITextField alloc] initWithFrame:CGRectMake(5, 5, 300, 30)];
txtEmail.placeholder = #"Email";
[cell.contentView addSubview:txtEmail];
[txtEmail release];
}
else if(indexPath.row==2){
cell.textLabel.text = #"Select Date of Birth";
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
// Configure the cell...
return cell;
}
thanks in advance
Pankaj
You need to create your text fields only in the block of code that inits the cell. Remember that the table view recycles cells so as you scroll off the screen you get a reused and recycled cell that already has a textfield. You are then creating a new textfield and overlaying the new textfield on the existing one, hence you get overlapping.
here is your code properly refactored
- (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];
//create the textField here, and we will reuse it and reset its data for each row.
UITextField *txtField = [[UITextField alloc] initWithFrame:CGRectMake(5, 5, 300, 30)];
[cell.contentView addSubview:txtField];
txtField.tag=110; //should declare a constant that uniquely defines your textField;
[txtField release];
}
// Configure the cell...
//ok, now we retrieve the textField and set its data according to the row.
UITextField *txtField = (UITextField *)[cell.contentView viewWithTag:110];
if(indexPath.row==0) {
txtField.placeholder = #"Full Name";
}
else if(indexPath.row==1) {
txtField.placeholder = #"Email";
}
else if(indexPath.row==2){
txtField.placeholder = nil; //? did you mean to set something here?
cell.textLabel.text = #"Select Date of Birth";
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
return cell;
}
I have just modified the previous one for missing an else condition which made an bad access error. The modified code is below:
You need to create your text fields before the block of code that inits the cell and init and add this text field in the block of code that inits the cell. Remember that the table view recycles cells so as you scroll off the screen you get a reused and recycled cell that already has a textfield. You are then creating a new textfield and overlaying the new textfield on the existing one, hence you get overlapping.
here is your code properly refactored
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITextField *txtField;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
//init the textField here, and we will reuse it and reset its data for each row.
txtField = [[UITextField alloc] initWithFrame:CGRectMake(5, 5, 300, 30)];
[cell.contentView addSubview:txtField];
txtField.tag=110; //should declare a constant that uniquely defines your textField;
[txtField release];
}
else{
// if the textfield is alread created and now dequed
//ok, now we retrieve the textField and set its data according to the row.
txtField = (UITextField *)[cell.contentView viewWithTag:110];
}
if(indexPath.row==0) {
txtField.placeholder = #"Full Name";
}
else if(indexPath.row==1) {
txtField.placeholder = #"Email";
}
else if(indexPath.row==2){
txtField.placeholder = nil; //? did you mean to set something here?
cell.textLabel.text = #"Select Date of Birth";
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
return cell;
}
For my current project i need to have a table in which contains textfield in each cell, the number of cells and textfield must be dynamic, it's depends on the number of data in a MutuableArray. I have the textfield in cells working, but i can't get/set the textfield value. I wonder if you guys can help me out or at least correct me what I did wrong? Thank's alot in advance. See code snippets below:
// Adds textfield into cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSUInteger row = indexPath.row;
X10ArchiefIndexDefs *curIndex = [indexDefinities objectAtIndex:row];
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
BOOL bShowSelection = ([curIndex.HasVasteWaarden isEqualToString:#"false"]);
if (bShowSelection) {
bShowSelection = !([curIndex.DataType isEqualToString:#"Datum"]);
}
if ([indexPath section] == 0) {
if (bShowSelection) {
cell.accessoryType = UITableViewCellAccessoryNone;
} else {
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
}
UITextField *editField = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
editField.adjustsFontSizeToFitWidth = YES;
editField.textColor = [UIColor blackColor];
editField.placeholder = curIndex.Naam;
editField.keyboardType = UIKeyboardTypeDefault;
editField.returnKeyType = UIReturnKeyNext;
editField.backgroundColor = [UIColor whiteColor];
editField.autocorrectionType = UITextAutocorrectionTypeNo; // no auto correction support
editField.autocapitalizationType = UITextAutocapitalizationTypeNone; // no auto capitalization support
editField.textAlignment = UITextAlignmentLeft;
editField.clearButtonMode = UITextFieldViewModeNever; // no clear 'x' button to the right
editField.tag = [curIndex.UID intValue];
[editField setEnabled: YES];
[cell addSubview:editField];
[editField release];
}
}
return cell;
}
In some case i'm using popovercontroller to display list of data. User can select a value uit of the popup. This code is executed when there is a value selected:
- (void)selectedValue:(NSString *) value {
//---update value of the text field ---
//The first attempt it doesn't put the text to text field
//static NSString *CellIdentifier = #"Cell";
//UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//
//if (cell == nil) {
// cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
//}
// second attempt it crashes
X10ArchiefIndexDefs *curIndex = [indexDefinities objectAtIndex:curRow.row];
int index = [curIndex.UID intValue];
UITextField *textField = (UITextField *) [curCell viewWithTag: index];
if (textField) {
[textField setText:value];
}
[textField release];
[self.popOverController dismissPopoverAnimated:YES];
}
When cell is selected I'm making sure that the cell is saved for use later.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
X10ArchiefIndexDefs *curIndex = [indexDefinities objectAtIndex:indexPath.row];
if (!curIndex) {
return;
}
curRow = indexPath; // saves the selected row
if ([curIndex.VasteWaarden count] > 0) {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
curCell = cell; // saves the selected cell
CGRect frame = [cell.superview convertRect:cell.frame toView:self.view];
self.detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
detailViewController.delegate = self;
self.popOverController = [[[UIPopoverController alloc] initWithContentViewController:detailViewController] autorelease];
X10ArchiefIndexDefs *curIndex = [indexDefinities objectAtIndex:indexPath.row];
self.detailViewController.Values = curIndex.VasteWaarden;
[self.popOverController presentPopoverFromRect:frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
}
Again thank's alot in advance.
Cheers,
Inoel
In the second code snippet you are releasing the textField. You shouldn't do this because you haven't retained it. Because viewWithTag: simple gets a reference to the text field it doesn't retain the textField. So you are releasing it more times that it has been retained, so the retainCount reaches 0 and the textfield is dealloced from memory. Then when you attempt it the second time there is no textfield in the memory.
Just remove the:
[textField release];
From the second code snippet. If you don't understand why, then read some articles about memory management (just google it). It takes some time to understand it fully, at least I know it took me a while :)