ios MasterDetail app: UITextField in tableview not work - ios

I have a master detail app in ios, with SDK 7.0, Xcode 5, using ARC.
master has many items, detail has a table view. When I click on an item, the contents of tableview will change. This works well until I put a UITextField in each cell, because I want to edit the contents in the table.
The problem is: when I click on a new item, the old contents don't disappear,so the contents of a cell is a superposition of the new UITextField's text and the old UITextField's text.
The first normal tableview like this:
After I click on an new item, the tableview will like this:
The snippet of codes of master is:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
LHBPoetry *poetry = poetryArray[indexPath.row];
self.detailViewController.poetryId = poetry.poetryId;
}
I have tried a lot of things in the above method, for example, I make all instances of the detail view controller to be nil; table view's data array removeAllObejects; table view reloadData; It can't fix the problem.
The snippet of detail is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"detailCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
UITextField *textField = textField = [[UITextField alloc] initWithFrame:
CGRectMake(90, 12, 200, 25)];
textField.tag = indexPath.row;
textField.text =_sentenceArray[indexPath.row];
textField.clearsOnBeginEditing = NO;
textField.delegate = self;
textField.returnKeyType = UIReturnKeyDone;
[textField addTarget:self
action:#selector(textFieldDone:)
forControlEvents:UIControlEventEditingDidEnd];
[cell.contentView addSubview:textField];
textField.text = _sentenceArray[indexPath.row];
return cell;
}
I draw this tableview in Main.storyborad, It has a prototype cell with an identifier.
Any help will be appreciated.

k there is something i want to tell, wy because u are keep on adding the textfields for reused cells, there is not one textfield in the cell ..:) there are more then one text field's, because of that u are getting overlapped with one other, i think u are using default "master- detail" application, and modifying it..:)
oky for that u need to modify like below
in master controller
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if(cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
UITextField *textField = [[UITextField alloc]initWithFrame:CGRectMake(2, 3, 300, 30)];
[textField addTarget:self action:#selector(textFieldDone:) forControlEvents:UIControlEventEditingDidEnd]; //hear u are adding once initially
textField.tag = 100;
[cell addSubview:textField];
}
NSString *object = _objects[indexPath.row];//_objects is mutable array holding the sentences or names
UITextField *textField = (UITextField *)[cell viewWithTag:100];//after that u are reusing the textfields
textField.text = object;
textField.tag = indexPath.row;
return cell;
}
now you are creating the cell thats wy u dont want the prototype cell remove it from story board
in the above u removed the custom cell becz u are creating the cell in the code it self
now in the method
- (void) textFieldDone:(UITextField *)inTextFIeld
{
int index = inTextFIeld.tag;
[_objects replaceObjectAtIndex:index withObject:[inTextFIeld text]];
[self.masterTableVIew reloadData];//made connection to ur tableview
}

Related

Cell and TextField not showing serialwise in UITableView

I am using UITextField, and every row have a CellLable and TextField. Lable and TextField data comes from array. While running the app, all data are comes fine but when scrolling the Tableview, Last 2-3 Rows unorganized.
NSMutableArray
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
ArrFieldData= [NSMutableArray arrayWithObjects:#"Fist Name", #"Last Name",#"User Name", #"Password",#"Confirm Password", #"Gender",#"DOB", #"Profile Pic",#"Deparment", #"Joining Date",#"Education", #"Role", nil];
Now cellForRowAtIndexPath Function
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
UITextField *txtField ;
if (cell ==nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
txtField = [[UITextField alloc]initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width/3 + 40, 2, [UIScreen mainScreen].bounds.size.width/2, cell.layer.frame.size.height -5)];
[self setUpCell:cell withIndexPath:indexPath withTextField:txtField];
}
[self UpdateCell:cell withIndexPath:indexPath withTextField:txtField];
return cell;
}
SetUp Cell Function
-(void)setUpCell:(UITableViewCell *)cell withIndexPath:(NSIndexPath *)indexPath withTextField: (UITextField *)txtField {
cell.textLabel.text = [ArrFieldData objectAtIndex:indexPath.row];
cell.textLabel.font = [UIFont systemFontOfSize:12.0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
txtField.tag = indexPath.row+1;
txtField.layer.borderColor = [UIColor grayColor].CGColor;
txtField.delegate = self;
txtField.layer.borderWidth = 1.0f;
txtField.layer.cornerRadius = 4.0f;
txtField.placeholder = cell.textLabel.text;
txtField.font = [UIFont systemFontOfSize:12.0];
[cell.contentView addSubview: txtField];
}
Update Cell Function
-(void)UpdateCell:(UITableViewCell *)cell withIndexPath:(NSIndexPath *)indexPath withTextField: (UITextField *)txtField {
[self setUpCell:cell withIndexPath:indexPath withTextField:txtField];
}
First time Running the application, It is showing all cell and textfield data are Serialize. but when scroll some cell and TextField are not serialize as per Array Value. I am attaching the Simulator Screenshot.
First Screenshot for First time running, and second for when i scroll the Tableview. See the last 4-5 cell and Textfield Placeholder text. They are un-organized. I want it shouldn't change.
As you are using reusable cells, like
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
UITextField *txtField ;
if (cell ==nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
txtField = [[UITextField alloc]initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width/3 + 40, 2, [UIScreen mainScreen].bounds.size.width/2, cell.layer.frame.size.height -5)];
[self setUpCell:cell withIndexPath:indexPath withTextField:txtField];
}
[self UpdateCell:cell withIndexPath:indexPath withTextField:txtField];
return cell;
}
UITableView uses the concept of reusable cell to achieve maximum performance by reducing the memory consumption, and to exploit this feature of reusing cells you can use the above UITableView's API's to achieve that.
But before using any feature it's very important to understand the working and the usage of any feature.
In your above implementation of tableView: cellForRowAtIndexPath: method, you have used the concept of cell reusability.
If the cells doesn't exist and are created for the first time, than they are allocated(every subview is created and added on the content view of the cell), customized and initialized with the data from the data source of the respective index path.
But in case the cells are reused(as they were already created for any other index path), there subviews exist with the data already filled for the previous index path for which it was created.
Now there are two things we can do to use already created cell for the current index path,
1) if the cells contain subview with data then remove the subviews and recreate the new ones, customize and populate them with the data.
2) rather than releasing the previous subviews and creating new ones, refill the data for the data model of the corresponding index path.
In your case, if the cell is being created for any index path, than the text filed for it is also created and if it's reused than the new text field is not created and it's being reused from the previously created cell thus the issue of the placeholder text not matching with the left text.
So, in order to solve your problem I think you should either create the textfield when the cell is created and if the cells are reused than refill the data in the text filed from the data source of the corresponding index path.
Your problem is due to a feature of UITableView. When you scroll a UITableView the indexPath is updated so you are not getting the index values you are expecting from the tableView.
Instead of adding a UITextField programmatically. Create a Custom UITableViewCell and from the method cellForRowAtIndexPath: update the placeHolder of your UITextField. The tableView will take care of scrolling for you.
Use this code :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
UITextField *txtField ;
if (cell ==nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
cell.textField.placeholder= cell.textLabel.text;
}
cell.textField.placeholder= cell.textLabel.text;
return cell;
}

Add a UITextField that retains its text in a UITableViewCell

How do I achieve a UITableViewCell with a textField in it? Ive been through a few similar questions on StackOverflow, but I find most of them deal with cases where the tableView's display is always constant and the know exactly what values go where. For my implementation the number of section and number of rows per section are determined by the user and could be anything. I have been able to get a textField in the cell but I find any text entered is lost when I scroll the table and the cell disappears from view. This is what i have so far
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.myTableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
UITextField *myTextField = [[UITextField alloc]
initWithFrame:CGRectMake(215, (cell.contentView.bounds.size.height-30)/2, 60, 30)];
[myTextField setDelegate: self];
myTextField.tag = indexPath.section;
NSLog(#"%ld", (long)myTextField.tag);
myTextField.placeholder = #"0%";
myTextField.borderStyle = UITextBorderStyleRoundedRect;
[cell addSubview:myTextField];
cell.textLabel.text = self.cellLabels[indexPath.section];
return cell;
}
I know what the problem is, I just cant figure out a work around. Even if I store everything the user enters in each textField in an array somehow, I cant set the text for each field when it return from being off screen as the cellForRowAtIndexPath gets called again and the textField is redrawn.
This is pretty much what I want, functionality wise. But "Paper1" and "Paper2" may be different sections...
Use a view model. Store the text for each cell in an array and then set the text in cellForRowAtIndexpath.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.myTableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
UITextField *myTextField = [[UITextField alloc]
initWithFrame:CGRectMake(215, (cell.contentView.bounds.size.height-30)/2, 60, 30)];
[myTextField setDelegate: self];
myTextField.tag = indexPath.section;
NSLog(#"%ld", (long)myTextField.tag);
myTextField.placeholder = #"0%";
myTextField.borderStyle = UITextBorderStyleRoundedRect;
myTextField.text = [self textForCellAtIndexPath:indexPath];
[cell addSubview:myTextField];
cell.textLabel.text = self.cellLabels[indexPath.section];
return cell;
}

Managing UITableViewCell selected states

I have UITableViewController with a static table view and 2 sections. The first section has two cells, with a layout Table View Cell > Content View > Text Field.
The second section of table view cells has a layout that is Table View Cell > Content View > Label - and the cells expand when they're selected by using beginUpdates and endUpdates and reporting cell heights via tableView:heightForRowAtIndexPath:.
Right now, when I touch one of the first sections' cells, the keyboard comes up and the cursor is placed in the text field, but the cell is not selected - which means that if I had previously selected one of the cells in the second section, it would remain selected (and therefore expanded).
Also, if I have selected a cell in the first section with the text field given first responder, then I select a cell in the second section, the cell expands, but the first cell does not resign first responder and dismiss the keyboard.
Did I layout my table view incorrectly such that the cell selected states are not managed automatically and if not: what is the proper way to manage the selected states of the UITableViewCells?
I dont know how you have written the code. But from above information I have created one sample application. The code is as below and it is working as you want.
I have considered the table with 2 section.
First section has the textfield on Cell.
Second section has the UIlabel on the cell.
txtFieldCopy is of type UITextField declared in .h of class.
Please check the way I have assigned the Tag to the view as we need it to get the indexpath.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCellStyle style =UITableViewCellStyleSubtitle;
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
int iTag=[indexPath row]+1;
txtFieldCopy=nil;
if(indexPath.section==1)
{
UILabel *lblFirst=nil;
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:style reuseIdentifier:MyIdentifier];
lblFirst = [[UILabel alloc] initWithFrame:CGRectMake(45, 0, 100,
40)] ;
lblFirst.tag=iTag;
[cell.contentView addSubview:lblFirst];
lblFirst=nil;
}
lblFirst = (UILabel *)[cell.contentView viewWithTag:iTag];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
lblFirst.text =#"Label 1";
}
else
{
UITextField *txtFirst=nil;
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:style reuseIdentifier:MyIdentifier];
txtFirst = [[UITextField alloc] initWithFrame:CGRectMake(40, 0, 50,
40)] ;
txtFirst.tag=iTag;
txtFirst.delegate=(id)self;
[cell.contentView addSubview:txtFirst];
txtFirst=nil;
}
txtFirst = (UITextField *)[cell.contentView viewWithTag:iTag];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
txtFirst.text =#"text 1";
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(txtFieldCopy)
{
[txtFieldCopy resignFirstResponder];
txtFieldCopy=nil;
}
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
NSLog(#"%d",textField.tag);
NSIndexPath *iRowId =[NSIndexPath indexPathForRow:(textField.tag-1) inSection:0];
[tblSample selectRowAtIndexPath:iRowId animated:NO scrollPosition:UITableViewScrollPositionMiddle];
txtFieldCopy=textField;
}
Make sure if suppose in between you are reloading the table view then txtFieldCopy=nil; in the cellForRowAtIndexPath get called and set to null. so you can ignore this line. But before please check whether you are calling it again and again.
Let me know if it worked for you or not. I am sure it definitely work for you

UITextField in UITableViewCell crash

I have a text field on custom tableview cell in right half side. When I directly click on the text field am getting the keyboard. But when I clicked on the cell directly am getting the crash.
In table view didSelectRowAtIndexPath method, I have the code
[cell.txtField becomeFirstResponder];
In the console log am getting this below message:
no index path for table cell being reused
Reference crash here
IN your screen shot you are calling:
[cell.txvalue becomeFirstResponder];
Do you mean:
[cell.textField becomeFirstResponder];
?
I'm guessing cell.textValue is a string ?
As for the console log, are you calling setClearsOnInsertion property enabled on your textview ?
first of all you create configure cell as below
- (void)configureCellAcountSet:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
UITextField *txt_UserName = [[UITextField alloc] initWithFrame:CGRectMake(85, 105, 150, 25)];
txt_UserName.borderStyle = UITextBorderStyleRoundedRect;
txt_UserName.font = [UIFont systemFontOfSize:13];
txt_UserName.autocorrectionType = UITextAutocorrectionTypeNo;
txt_UserName.keyboardType = UIKeyboardTypeDefault;
txt_UserName.returnKeyType = UIReturnKeyDone;
txt_UserName.clearButtonMode = UITextFieldViewModeWhileEditing;
txt_UserName.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
txt_UserName.delegate = self;
[[cell contentView] addSubview:txt_UserName];
}
After taht confige cell use in table delegete mehode. Dont do anything didSelectRowAtIndexPath.when you click on textfield it open keyboard and click on cell nothing done there.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"section0";
tbl_setting.layer.cornerRadius = 10.0;
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
//if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[self configureCellAcountSet:cell atIndexPath:indexPath];
}
You have to implement UITextField delegate.

How can I prevent a button from disappearing while selecting a cell of TableView?

I have a custom cell in TableView and there is a button in the cell. When I select the cell, the background turns to blue and the button disappears. Is there any way to prevent this?
The cellForRowAtIndexPath like this -
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
MyTableCell *cell = (MyTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[MyTableCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
Search *current = [self.retrievedTweets objectAtIndex:indexPath.row];
cell.textLabel.text = current.text;
cell.textLabel.font = [UIFont systemFontOfSize:15.0];
cell.textLabel.numberOfLines = 2;
cell.detailTextLabel.text = current.name;
cell.imageView.image = current.userImage;
btnUncheck =[[UIButton alloc] initWithFrame:CGRectMake(400, 35, 20, 20)];
btnUncheck.backgroundColor = [UIColor redColor];
btnUncheck.layer.cornerRadius = 10;
btnUncheck.hidden =NO;
btnUncheck.tag=indexPath.row;
//[btnUncheck addTarget:self action:#selector(didSelectRowAtIndexPath:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:btnUncheck];
return cell;
}
use custom image for selected table cell. or try with buttons images.
paste below line in your tableview Delegate Method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
///// your code ///////////
cell.selectionStyle=UITableViewCellSelectionStyleNone;
//// your code////////
}
here your blue backgound will not display..
What you can do is this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{[tableView deselectRowAtIndexPath:indexPath animated:YES];}
Hope this helps
Also, if you have already implemented this, what else do you have in this delegate method?
Instead of this line:
btnUncheck = [[UIButton alloc] initWithFrame:CGRectMake(400, 35, 20, 20)];
use:
btnUncheck = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
[btnUncheck setFrame:CGRectMake(400, 35, 20, 20)];
Create a "custom" view with background color clear and set to it.
UIView* vista=[[[UIView alloc] init] autorelease];
vista.backgroundColor=[UIColor clearColor];
cell.selectedBackgroundView=vista;
The way to fix this right, is to create a custom cell that you then add a button to in the xib editor.
So, in xib editor, add a 'UITableViewCell' item. Then add the button to that cell item in the xib editor. You'll then attach your custom cell to the table in the corresponding .m file here:
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
I have tried this out with just a one row table and the custom cell tied as a property from the xib to the .h file that has the table view. The highlight is there and just grays out the button (still viewable). To get this to work with more rows is more involved. You'll need to load the custom utableviewcell xib and alloc your custom cell dynamically for that to work.

Resources