hello every one
i have table view with one cell,and i make on this cell a UITextView that the user can write what he want,this is the code inside the cellForRow:
static NSString *CellIdentifier = #"Cell";
UITextView *text;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
text = [[UITextView alloc]initWithFrame:CGRectMake(1, 5, 200, 140)];
text.tag = 1;
UIView *statusView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 300, 150)];
statusView.tag = 0;
[statusView addSubview:text];
[cell.contentView addSubview:statusView];
}
else {
text = (UITextView *)[[cell.contentView viewWithTag:0] viewWithTag:1];
}
i want to make a save button and i want to know how i can take the text from this UITextView from another method in the class.
thx
Use UIButton to create the button and set a action (method) for that will be called when you click on button.
-(void) buttonPressed:(id) sender
{
//First get the cell (We know we have the only one cell).
// Create an NSIndexPath to access the cell from UITableView.
NSIndexPath *myIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
//Now We can access the cell using UITableView instance.
UITableViewCell *myCell = [myTabelView cellForRowAtIndexPath:myIndexPath];
//Now access the instance of UITextView using viewWithTag property of UIView.
UITextView* myTextView = (UITextView*) [myCell viewWithTag:1];
//Now you could get the text. :)
NSString* myTextViewText = myTextView.text ;
}
Related
I am new to iphone.I have a small question that is,I have a class CustomCell in that i have declare all elements which i have required like the below
// CustomCell.h
here in this class i am setting the getter and setter methods to TitleLabel, PercentageLabel, ProgressView, downloadButton
// CustomCell.m
here in this class set the frame to above all,and set the image to the download button also here
screen shot of my output screen is
// In my table view i have a download button when we click that the following method will executes
-(void)downloadButtonClicked:(id)sender
{
NSLog(#"download button clicked");
int index = [sender tag];
NSLog(#"index of the cell is %d",index);
UIButton *button = (UIButton*)sender;
UITableViewCell *cell = (UITableViewCell *)[[button superview] superview];
UILabel *titleLabel = (UILabel *)[cell viewWithTag:100];
NSLog(#"label text =%#",titleLabel.text);
UIView *senderButton = (UIView*) sender;
NSIndexPath *indexPath = [tableView indexPathForCell: (UITableViewCell*)[[senderButton superview]superview]];
NSLog(#"indexpath is %d",indexPath.row);
CustomCell *customCell = [[CustomCell alloc]init];
progressView = [[UIProgressView alloc]init];
// [customCell.contentView insertSubview:progressView atIndex:indexPath.row];
[customCell.contentView addSubview:progressView];
selectedBookTitle = titleLabel.text;
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSMutableArray *allDownloadLinks;
biblePlayerViewController = [[BiblePlayerViewController alloc]init];
allDownloadLinks = [biblePlayerViewController allDownloadLinks];
NSLog(#"all Download Links are %#",allDownloadLinks);
biblePlayerViewController.indexOfSelectedBookTitle = [[appDelegate getBookNames]indexOfObject:selectedBookTitle];
Download* download = [Download downloadWithTitle:selectedBookTitle url:[NSURL URLWithString:[NSString stringWithFormat:#"http://www.audiotreasure.com/%#.zip",[allDownloadLinks objectAtIndex:(biblePlayerViewController.indexOfSelectedBookTitle)]]]PathtoSave:documentsPath];
[[DownloadManager sharedDownloadManager] queueDownload: download];
}
// In cellForRowAtIndexPath tableview delegate method I have written code like this
- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
CustomCell *cell = [_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
NSLog(#"indexpath.row is %d",indexPath.row);
NSLog(#"downloadmanager is %d",[[[DownloadManager sharedDownloadManager]getDownloads]count]);
/* if (indexPath.row<[[[DownloadManager sharedDownloadManager] getDownloads]count])
{
cell.TitleLabel.text = ((Download*)[[[DownloadManager sharedDownloadManager] getDownloads] objectAtIndex:indexPath.row]).title_;
cell.ProgressView.progress = (float)(((Download*)[[[DownloadManager sharedDownloadManager] getDownloads] objectAtIndex:indexPath.row]).PercentageDownloaded_ )/100.0f;
cell.PercentageLabel.text = [NSString stringWithFormat:#"%d %%",((Download*)[[[DownloadManager sharedDownloadManager] getDownloads] objectAtIndex:indexPath.row]).PercentageDownloaded_];
}
else
{
[tableView reloadData];
}*/
NSString *titleLabel = [[appDelegate getBookNames]objectAtIndex:indexPath.row];
cell.TitleLabel.text = titleLabel;
cell.downloadButton.tag = indexPath.row;
NSLog(#"tag is %d",cell.downloadButton.tag);
[cell.downloadButton addTarget:self action:#selector(downloadButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
My question is I have 66 cells in tableview in screen shot we have a bookname called Revelation.It has a 66th cell in my tableview (index is 65).Here when i click the download button in that cell,I have to show progress view in that particular cell only (65th cell).I have reload the table view for every 1 sec also because after placing the progress view we have to show the progress in that progress view in that cell.So, how can we place a progress view in that particular cell index.
Why don't you add the progress view in the cell from the beginning?
have it initially hidden and when you touch the download button you tell the cell to show it.
i see that you store the indexPath.row of the cell in the download button tag. You could use that to find out what cell was selected something like below.
NSIndexPath *cellIndexPath = [NSIndexPath indexPathForRow:sender.tag inSection:0];
CustomCell *cell = (CustomCell *)[tableView cellForRowAtIndexPath:nowIndex];
[cell showProgressBar];
i wrote the code of top of my head..didn't tested it.
Might be a stupid question.
I have a UITableview, with multiple cells. In each cell I am displaying some data. I am not using cell's text property to display data. Instead I have a custom label inside my cell, which is displaying the text.
My question is:
When I click on the cell, I need to retrieve the data from the cell. How can I do this.
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
UILabel *CellTextlabel = [[UILabel alloc] init];
CellTextlabel.tag = 222;
[CellTextlabel setFrame:CGRectMake(40, 5, 200, 20)];
[cell.contentView addSubview:CellTextlabel];
[CellTextlabel release];
}
UILabel *editCellTextlabel = (UILabel *)[cell.contentView viewWithTag:222];
editCellTextlabel.font = [UIFont boldSystemFontOfSize:18];
editCellTextlabel.text = contact.lastName;
In your didSelectRowAtIndexPath method, you may do it as follows:
UITableViewCell *cell = (UITableViewCell *)[self.tableViecellForRowAtIndexPath:indexPath];
UILabel *textLabel = (UILabel *)[cell viewWithTag:222];
Now you can retrieve the data in the cell's UILabel using textLabel.text
You could get access to that label in didSelectRowAtIndexPath: with
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UILabel *myLabel = [cell.contentView viewWithTag:222];
But probably worth asking, why are you adding a sub label instead of using the textLabel property? you can modify its frame, settings etc and then you don't have to worry about tags, since this property is exposed in UITableViewCell by default
In the -tableView:didSelectRowAtIndexPath: method, you can get the data from your tableView's array:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
id objectForCell = [self.myArray objectAtIndex:indexPath.row];
//do what you want with the above data.
}
After using Run->Run with Performance tool->Leaks on my application, it finds a leak, but I don't know if it is a glitch by the tool?
I start the application by selecting a button, which opens a tableview (no leaks).
tableview appears and if I don't touch anything (no leaks).
If I select the first cell and cursor appears blinking (3 to 4 seconds later, leak)??
I did find something weird, in my tableview, if I try selecting any other cell, besides the first one, it will not become the first responder (this might not have to do with anything)?
If anyone has come across this or can spot or direct me to where this could be happening please let me know? Thank you.
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
UITextField *FirstField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 130, 25)];
FirstField.delegate = self;
FirstField.tag = indexPath.row; [cell.contentView addSubview:FirstField];
FirstField.returnKeyType = UIReturnKeyNext;
[FirstField release];
return cell;
}
The memory leak is that due to every time you call the function you are allocating a UITextField and adding it to the cell.
Cells are reused and each time the cell is accessed to determine the content a new UITextField is added to the cell and stacked onto of each other
Move the allocation of FirstField to where the cell is allocated so that it can be reused.
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UITextField *FirstField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 130, 25)];
FirstField.tag = 1
[cell.contentView addSubview:FirstField];
[FirstField release];
}
UITextField *field = (UITextField *)[cell.contentView viewWithTag:1];
field.delegate = self;
field.returnKeyType = UIReturnKeyNext;
return cell;
I also see that you are using the field.tag to store the indexPath.row value of the cell, in that cause you might have to search the view hirachy of cell.contentView to find the TextField subview.
I have a UITableView with about 20 cells, in each cell there are three UITextFields. I did NOT subclass UITableViewCell, but when setting up each cell I set the textfields tag value to a constant plus the row number. So for each row the tag of the textfield is incremented by one.
When I run the app and enter a value in for example row one, it may reappear on row 12. The behavior is not the same each time i run the app.
I should add that I have an array storing the contents entered in each textfield. When a textfield is edited, I save the new value to the array and when the cell is again requested by the tableview i set the textfields value to that stored in the array.
Does this have something to do with reusing UITableViewCells?
When reusing a cell, can textfields in different rows get the same tag numbers? Say for example that the first cell (textfield tag=1001) is reused on row 12, then we have two textfields with the same tag number. If I then enter a value on row 1 and later load row 12, the value from cell one will be loaded from the array and put in row 12 also.
If this is happening, how do I fix it?
Each cell does not have a reference to the textfield, so I don't think I can edit a textfield's tag value by just having access to the cell which it is in.
EDIT:
Here is the code for UITableView:cellForRowAtIndexPath:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
//Modify cell, adding textfield with row-unique index value
cell = [self modifyCellForHoleInfo:cell atIndexPath:indexPath];
}
cell.accessoryType = UITableViewCellAccessoryNone;
// Load value for textfield stored in dataArray
((UITextField *)[cell viewWithTag:1000+indexPath.row]).text = [dataArray objectAtIndex:indexPath.row];
Thanks!
The issue is that when the cell is reused (i.e. dequeueReusableCellWithIdentifier returns non-nil), the cell is returned with the existing UITextView. To maintain the uniqueness of the tags, it'll be better to remove any previous UITextField:
- (void)removeExistingTextSubviews:(UITableViewCell *)cell
{
NSMutableArray *toRemove = [NSMutableArray array];
// I don't know if you have non-TextField subviews
for (id view in [cell subviews]) {
if ([view isKindOfClass:[UITextField class]] && view.tag >= 1000) {
[toRemove insert:view];
}
}
for (id view in toRemove) {
[toRemove removeFromSuperView];
}
}
...
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
} else {
[self removeExistingTextSubviews:cell];
}
//Modify cell, adding textfield with row-unique index value
cell = [self modifyCellForHoleInfo:cell atIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
// Load value for textfield stored in dataArray
((UITextField *)[cell viewWithTag:1000+indexPath.row]).text = [dataArray objectAtIndex:indexPath.row];
Please note that I haven't compiled the code, but it should serve as a starting point.
Just get the textfield text into Dictionary setObject by label text and again check by label Text assign the text to corresponding Textfield.. here is my code...
//In Interface
NSMutableDictionary *amounts;
amounts =[[NSMutableDictionary alloc]init];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"MoneyEntryIdentifier";
static NSString *CellNib = #"MoneyEntry";
MoneyEntryTableViewCell *cell = (MoneyEntryTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
cell = (MoneyEntryTableViewCell *)[nib objectAtIndex:0];
}
UILabel *lblname = (UILabel *) [cell lblMemName];
lblname.tag =100;
UITextField *txtfield = (UITextField *)[cell textAmount];
txtfield.tag =indexPath.row;
[txtfield addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
lblname.text = tabledata[indexPath.row];
txtfield.placeholder = [NSString stringWithFormat:#"%ld",(long)indexPath.row];
if ([amounts valueForKey:lblname.text] != nil) {
txtfield.text = [amounts valueForKey:lblname.text];
} else {
txtfield.text = #"";
}
cell.selectionStyle =UITableViewCellSelectionStyleNone;
return cell;
}
-(void)textFieldDidChange:(UITextField *)txtField
{
UILabel *label = (UILabel *)[txtField.superview viewWithTag:100];
NSString *labelString = label.text;
NSString *textFieldString = txtField.text;
[amounts setObject:textFieldString forKey:labelString];
}
Change the nib to your tableview cell...
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;
}