I have a UITextField in UITableViewCell the text property is not updating.
My tableview delegate:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
KAPInputTableViewCell *cell = [self.registerTableView
dequeueReusableCellWithIdentifier:KAPInputCellIdentifier];
if (!cell) {
cell = [[KAPInputTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:KAPInputCellIdentifier];
}
switch (indexPath.row) {
case 0:
cell.inputTextField.placeholder = KAPLocalizedString(#"email", #"E-mail address");
cell.inputTextField.text = #"Test";
cell.tag = 0;
cell.errorLabel.text = self.emailError;
self.emailCell = cell;
self.emailTextField = cell.inputTextField;
break;
}
cell.inputTextField.delegate = self;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
Then when I call,
NSLog(#"%#", self.emailTextField.text);
Later in my ViewController on the press of a button the edited text still returns "Test" while I changed the input value.
Please help.
I think you should just implement the UITextField delegate method:
- (void)textFieldDidEndEditing:(UITextField *)textField{
NSLog(#"%#", textField.text);
}
Here you will see your textField updated.
Related
I have a tableviewcontroller that has dynamic controls created in cells. If it's a dropdown type, I take the user to a different tableviewcontroller to select the value. Once selected, I pop back and reload the data, but when I do that it overwrites the cells on top of one another. I know this is because I'm reusing the cells, but I cannot seem to figure out how to prevent it.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
EWHInboundCustomAttribute *ca = [visibleCustomAttributes objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
cell.tag=indexPath.row;
if (ca.CustomControlType == 1) {
cell.detailTextLabel.hidden=true;
cell.textLabel.hidden=true;
UITextField *caTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 185, 30)];
caTextField.adjustsFontSizeToFitWidth = YES;
caTextField.textColor = [UIColor blackColor];
caTextField.placeholder = ca.LabelCaption;
if (ca.ReadOnly) {
[caTextField setEnabled: NO];
} else {
[caTextField setEnabled: YES];
}
caTextField.text=nil;
caTextField.text=ca.Value;
caTextField.tag=indexPath.row;
caTextField.delegate=self;
[cell.contentView addSubview:caTextField];
} else if (ca.CustomControlType == 4) {
cell.detailTextLabel.text=ca.Value;
cell.textLabel.text=ca.LabelCaption;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else {
cell.detailTextLabel.hidden=true;
cell.textLabel.hidden=true;
UITextField *caTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 185, 30)];
caTextField.adjustsFontSizeToFitWidth = YES;
caTextField.textColor = [UIColor grayColor];
caTextField.placeholder = ca.LabelCaption;
[caTextField setEnabled: NO];
caTextField.text = ca.Value;
caTextField.tag=indexPath.row;
caTextField.delegate=self;
[cell.contentView addSubview:caTextField];
}
return cell;
}
Instead of creating the UITextfield each time I would suggest at least using [UIView viewWithTag:tag] to capture the same UITextField object.
I'd suggest you to create custom UITableViewCell subclass and put all subviews related logic there.
Next, in order to reset/clear cell before reuse - you should override prepeareForReuse function.
Swift:
override func prepareForReuse() {
super.prepareForReuse()
//set cell to initial state here
}
First,I suggest you to use custom cells.If not and your cells are not so many,maybe you can try unique cell identifier to avoid cell reuse:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// unique reuseID
NSString *cellReuseID = [NSString stringWithFormat:#"%ld_%ld", indexPath.section, indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellReuseID];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellReuseID];
// do something
}
return cell;
}
Hope it's helpful.
I'm attempting to create an inline DatePicker inside a TableView cell, similar to this and this SO thread.
I create the date picker using the method below, which is called when the view is loaded:
- (void)createDatePicker{
_datePicker = [[UIDatePicker alloc]init];
_datePicker.datePickerMode = UIDatePickerModeTime;
_datePicker.clipsToBounds = YES;
_datePicker.backgroundColor = [UIColor colorWithRed:0.922 green:0.937 blue:0.949 alpha:1];
NSLog(#"date picker created");
}
I then check to see if the bottom row of the third section in my table view is selected. If it is, and the date picker already isn't showing, then I call the method to show the date picker's cell:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == HourTimeZoneRow && self.datePickerIsShowing == NO)
{
NSLog(#"Time of day section");
[self showDatePickerCell];
} else
{
[self hideDatePickerCell];
}
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Below are the methods to show the date picker's cell:
- (void)showDatePickerCell {
[self.tableView addSubview:_datePicker];
self.datePickerIsShowing = YES;
self.datePicker.hidden = NO;
[self.tableView reloadData];
NSLog(#"Show date picker");
}
...and hide the cell:
- (void)hideDatePickerCell {
self.datePickerIsShowing = NO;
self.datePicker.hidden = YES;
[self.tableView reloadData];
NSLog(#"Hide date picker");
}
Below is the method to determine if the table view needs to add an extra cell to display the UIDatePicker.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
switch (section) {
case TableSectionOne:
return TotalRowsSection1;
break;
case TableSectionTwo:
return TotalRedZoneRows;
break;
case TableSectionThree:
if (self.datePickerIsShowing == YES) {
return TableSectionThree + 1;
}
else {
return TableSectionThree;
}
break;
default:
return 0;
break;
}
}
Finally, the method below is what is supposed to determine the height of the date picker's cell:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGFloat rowHeight = self.tableView.rowHeight;
if (indexPath.row == HourTimeZoneRow){
rowHeight = 164;
}
else {
rowHeight = self.tableView.rowHeight;
}
return rowHeight;
}
However, what's happening is that when the last row of the third section is selected, the date picker is displayed in the first row of the first section. Does anyone have any suggestions on what I'm doing wrong?
You're adding the datePicker to the tableView, not to a cell within the tableView.
Remove this line from showDatePickerCell:
[self.tableView addSubview:_datePicker];
Then add it (or unhide it) within the proper cell within cellForItemAtIndexPath.
(something like:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
if (indexPath.row == HourTimeZoneRow) {
// show the datePicker here
}
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
)
I an creating app that needs expand tableview feature like below screen. when i click the row the textbox and button will appear.when i click on textbox and press return from keyboard, application crashed.
When I tried to resign the text box showing in screenshot, application crashed,
I write Following Code...
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"AffiliationCell"];
cell.backgroundColor = [UIColor clearColor];
UILabel *lblTitle = [[UILabel alloc] initWithFrame:CGRectMake(15, 0, 130, 44)];
lblTitle.tag = indexPath.row+1;
lblTitle.font = [UIFont fontWithName:Oxygen_Regular size:13];
lblTitle.text = [NSString stringWithFormat:#"Affiliation %d",indexPath.row+1];
lblTitle.backgroundColor = [UIColor clearColor];
lblTitle.textColor = [UIColor blackColor];
[cell.contentView addSubview:lblTitle];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell* checkCell = [tableView cellForRowAtIndexPath:indexPath];
[tableView beginUpdates];
if ([indexPath compare:self.checkedIndexPath] == NSOrderedSame) {
self.checkedIndexPath = nil;
[viewScreenName removeFromSuperview];
} else {
//add view
[txtScreenName setClearsOnInsertion:YES];
viewScreenName.frame = CGRectMake(0, 45, viewScreenName.frame.size.width, viewScreenName.frame.size.height);
[checkCell.contentView addSubview:viewScreenName];
self.checkedIndexPath = indexPath;
}
[tableView endUpdates];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
if ([indexPath compare:self.checkedIndexPath] == NSOrderedSame) {
return expandedCellHeight; // Expanded height
}
return 44 ;
}
#pragma mark - TextField Delegate
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
tblAffiliations.frame = updatedFrame;
return TRUE;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
#try {
if (textField) {
[textField resignFirstResponder];
}
}
#catch (NSException *exception) {
NSLog(#"Exception %#",exception);
}
tblAffiliations.frame = currentFrame;
return TRUE;
}
Please Help.
It seems that you are using a textfield that is being deallocated. I think the best way to proceed is adding the textfield in each cell like you added your label and setting it to be hidden. On the didSelectRow delegate, you should set the label as hidden and the textfield not hidden. It is better to work with hidden flag that to remove and add from superview.
Wish it helps.
I create table view cell which contains my custom text field, subclass of UITextField. When i add text field to my cell i set
textField.textAlignment = NSTextAlignmentCenter;
I have placeholder on text field. When my cell appears it's alignment is something average between left and center. Then after editing it becoming center. I need center alignment right after creating cell. Can anyone help to solve this?
Edit
My CellForRowAtIndexPath method:
- (CTKMultiColumnTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *reuseIdentifier = [NSString stringWithFormat:#"cell%d",indexPath.section];
CTKMultiColumnTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
if (cell == nil) {
cell = [[CTKMultiColumnTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
[cell setFrameWithRect:CGRectMake(0, 0, tableView.frame.size.width, 34)];
}
cell.textField.placeholder = [_placeholders objectAtIndex:tableView.tag];
cell.delegate = self;
cell.relatedTableView = tableView;
return cell;
}
and part of willDisplayCell method
- (void)tableView:(UITableView *)tableView willDisplayCell:(CTKMultiColumnTableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
switch (tableView.tag) {
case 4:
cell.textField.leftView = nil;
cell.textField.rightView = nil;
cell.textField.textAlignment = NSTextAlignmentCenter;
cell.textField.keyboardType = UIKeyboardTypeNumberPad;
cell.isPickable = NO;
cell.valueLimitMin = 0;
cell.valueLimitMax = 1000;
if (((CTKRoom *)[_roomsArray objectAtIndex:indexPath.section]).heatedArea) {
cell.textField.text = [NSString stringWithFormat:#"%#", ((CTKRoom *)[_roomsArray objectAtIndex:indexPath.section]).heatedArea];
}
else cell.textField.text = #"";
break;
}
this part is example of setting properties to my cell
I solved my problem. The reason was
myTextField.rightViewMode = UITextFieldViewModeAlways;
In my case right view was necessary, so in case when it wasn't needed i set
myTextField.rightView.frame = CGRectMake(0, 0, 1, 0);
So basically I am getting the wrong data on every textField by scrolling my TableView (Everything is mixed up). I know, this is because the awesome optimization of the reusable cells in the UITableView, so the indexpath are changing constantly, but still I don't know how to solve this.
Having an UILabel in the same cell I solved this problem by adding a specific tag in every label view, so the tableview knows which data is going to return on a view but for some reason this is not possible for my textfield view.
Here is my code:
#define DESCRIPTION_TAG 10
#define TEXTFIELD_TAG 11
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Description Cell";
// Intatiating my own TableViewCell
CustomLocationCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (!cell){
cell = [[CustomLocationCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.rowText = (UILabel *) [cell viewWithTag:DESCRIPTION_TAG]; // returning view with unique tag
cell.rowTextField = (UITextField *)[cell viewWithTag:TEXTFIELD_TAG]; // NOT WORKING!!! Data get mix up
cell.rowTextField.delegate = cell; // sending the delegate to custom class cell
cell.delegate = self; // make connection with my #protocol
switch (indexPath.section) {
case 0:
cell.rowText.text = [self.descriptions objectAtIndex:indexPath.row];
cell.rowTextField.placeholder = [self.descriptionsPlaceholder objectAtIndex:indexPath.row];
break;
case 1:
cell.rowText.text = [self.rooms objectAtIndex:indexPath.row];
cell.rowTextField.placeholder = [self.contentPlaceholder objectAtIndex:indexPath.row];
break;
default:
break;
}
return cell;
}
Any help is appreciated.
Here is an update of my data source:
On my CustomTableViewCell I do have outlets for my UILabel and UITextfield
// UITableView DataSource
- (NSArray *)sections
{
if (!_sections){
_sections = [[NSArray alloc] initWithObjects:#"First Description", #"Second Descriptions", nil];
}
return _sections;
}
- (NSMutableArray *)rooms
{
if (!_rooms){
_rooms = [[NSMutableArray alloc] init];
}
return _rooms;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.sections.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
switch (section) {
case 0:
return [self.descriptions count];
break;
case 1:
return [self.rooms count];
break;
default:
break;
}
return 0;
}
I'm not sure exactly what you're trying to accomplish, but here's an example that works with labels and text fields with placeholder text. You'll notice that in cellForRowAtIndexPath, I set both the text and placeholder to nil, so that when a cell is reused, it doesn't have the wrong text in it. Also, when doing the text fields, I check if the array has placeholder text at that index, and if so, I reset the placeholder, and if not I reset the text.
In order for the text field delegate methods to work properly, each text filed needs a unique tag (not just one tag for labels and another for text fields) that I set equal to (indexPath.row + 1000*indexPath.section).
#import "TableController.h"
#import "CustomLocationCell.h"
#interface TableController ()
#property (strong,nonatomic) NSArray *descriptions;
#property (strong,nonatomic) NSMutableArray *descriptionsPlaceholder;
#property (strong,nonatomic) NSArray *rooms;
#property (strong,nonatomic) NSMutableArray *contentPlaceholder;
#end
#implementation TableController
- (void)viewDidLoad {
[super viewDidLoad];
self.descriptions = #[#"One",#"Two",#"Three",#"Four",#"Five",#"Six",#"Seven",#"Eight"];
self.descriptionsPlaceholder = [#[#"Placeholder1",#"Placeholder2",#"Placeholder3",#"Placeholder4",#"Placeholder5",#"Placeholder6",#"Placeholder7",#"Placeholder8"] mutableCopy];
self.rooms = #[#"Room1", #"Room2", #"Room3", #"Room4",#"Room5", #"Room6", #"Room7", #"Room8"];
self.contentPlaceholder = [#[#"ContentPH1",#"ContentPH2",#"ContentPH3",#"ContentPH4",#"ContentPH5",#"ContentPH6",#"ContentPH7",#"ContentPH8"] mutableCopy];
[self.tableView reloadData];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.descriptions.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Description Cell";
CustomLocationCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.rowTextField.delegate = self;
cell.rowTextField.tag = indexPath.row + 1000*indexPath.section;
cell.rowTextField.placeholder = nil;
cell.rowTextField.text = nil;
switch (indexPath.section) {
case 0:
cell.rowText.text = [self.descriptions objectAtIndex:indexPath.row];
if ([self.descriptionsPlaceholder[indexPath.row] hasPrefix:#"Placeholder"]) {
cell.rowTextField.placeholder = [self.descriptionsPlaceholder objectAtIndex:indexPath.row];
}else{
cell.rowTextField.text = [self.descriptionsPlaceholder objectAtIndex:indexPath.row];
}
break;
case 1:
cell.rowText.text = [self.rooms objectAtIndex:indexPath.row];
if ([self.contentPlaceholder[indexPath.row] hasPrefix:#"ContentPH"]) {
cell.rowTextField.placeholder = [self.contentPlaceholder objectAtIndex:indexPath.row];
}else{
cell.rowTextField.text = [self.contentPlaceholder objectAtIndex:indexPath.row];
}
break;
default:
break;
}
return cell;
}
-(void)textFieldDidEndEditing:(UITextField *)textField {
if (textField.tag >= 1000 && ![textField.text isEqualToString: #""]) {
[self.contentPlaceholder replaceObjectAtIndex:textField.tag - 1000 withObject:textField.text];
}else if (textField.tag < 1000 && ![textField.text isEqualToString: #""]) {
[self.descriptionsPlaceholder replaceObjectAtIndex:textField.tag withObject:textField.text];
}
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}