Saving UITextField text in cell into NSUserDefaults? - ios

I have seen every post that is close to this question, and still not finding something useful. I have textFields in every cell that is being used as a form for the user to fill out. Everything with the cells works fine except when scrolling, the input in the textFields disappears when the cell scrolls off screen. I know this is because of dequeue. But there should be a way to save the data entered so that it doesn't disappear when scrolling or exiting the app. I also want to be able to take this info and email it as a PDF, or document. What is the best way to achieve this? The code below is an example of how I am generating my cells etc.
.h file
#interface MasterViewController : UITableViewController <UITextFieldDelegate, UITextFieldDelegate, UITableViewDataSource, UINavigationBarDelegate>{
NSString* name_;
UITextField* nameFieldTextField;
}
// Creates a textfield with the specified text and placeholder text
-(UITextField*) makeTextField: (NSString*)text
placeholder: (NSString*)placeholder;
// Handles UIControlEventEditingDidEndOnExit
- (IBAction)textFieldFinished:(id)sender;
#property (nonatomic,copy) NSString* name;
.m file
#synthesize name = name_;
- (void)viewDidLoad{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
self.name = #"";
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
// Make cell unselectable and set font.
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.font = [UIFont fontWithName:#"ArialMT" size:13];
if (indexPath.section == 0) {
UITextField* tf = nil;
switch ( indexPath.row ) {
case 0: {
cell.textLabel.text = #"Name" ;
tf = nameFieldTextField = [self makeTextField:self.name placeholder:#"John Appleseed"];
nameFieldTextField.tag = 1;
[cell addSubview:nameFieldTextField];
break ;
}
// Textfield dimensions
tf.frame = CGRectMake(120, 12, 170, 30);
// Workaround to dismiss keyboard when Done/Return is tapped
[tf addTarget:self action:#selector(textFieldFinished:) forControlEvents:UIControlEventEditingDidEndOnExit];
}
return cell;
}
// Textfield value changed, store the new value.
- (void)textFieldDidEndEditing:(UITextField *)textField {
//Section 1.
if ( textField == nameFieldTextField ) {
self.name = textField.text ;
}
}
- (void)viewWillAppear:(BOOL)animated{
NSString *nameCellString = [[NSUserDefaults standardUserDefaults] stringForKey:#"nameCellString"];
nameFieldTextField.text = nameCellString;
}
- (void)viewWillDisappear:(BOOL)animated{
NSString *nameCellString = self.name;
[[NSUserDefaults standardUserDefaults] setObject:nameCellString forKey:#"nameCellString"];
}

There are actually two problems here, both of them being in your cellForRowAtIndexPath: implementation.
You are putting the text field into the cell, even if this cell is reused and already has a text field. Thus you are actually piling text field over text field, covering up the previously existing text field.
You are not putting the text back into the text field if there was already text in the text field for that row (index path).
In other words, the cells are (as you rightly say) reused, so it is up to you to take that fact into account. You must look at the state of the incoming cell, and reconfigure the cell accordingly.

First off, I urge you to consider creating a custom cell in a storyboard, and grabbing that. It's a lot easier than coding one, and I think it's the future. That said, look into populating your tableViews with NSArrays, instead of hard-coding strings into the cellForRowAtIndexPath method. I've taken the liberty of giving you an example of this.
The following is based on your code, and should be a copy/paste solution. Look it over, and see how it operates.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *titlesArray = #[#"Name", #"Birthday", #"Favorite Food"];
UITableViewCell *cell;
cell = [tableView dequeueReusableCellWithIdentifier:[NSString stringWithFormat:#"%i%i", indexPath.section, indexPath.row]];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
// Make cell unselectable and set font.
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.font = [UIFont fontWithName:#"ArialMT" size:13];
// Populate label from array
cell.textLabel.text = titlesArray[indexPath.row];
if (indexPath.section == 0) {
UITextField* tf = nil;
switch ( indexPath.row ) {
case 0: {
tf = nameFieldTextField = [self makeTextField:self.name placeholder:#"John Appleseed"];
nameFieldTextField.tag = 1;
[cell addSubview:nameFieldTextField];
break ;
}
// Textfield dimensions
tf.frame = CGRectMake(120, 12, 170, 30);
// Workaround to dismiss keyboard when Done/Return is tapped
[tf addTarget:self action:#selector(textFieldFinished:) forControlEvents:UIControlEventEditingDidEndOnExit];
}
// Set the reuse identifier to a unique string, based on placement in table
// This ensures that the textField will retain its text
cell.reuseIdentifier = [NSString stringWithFormat:#"%i%i", indexPath.section, indexPath.row];
}
return cell;
}
// Textfield value changed, store the new value.
- (void)textFieldDidEndEditing:(UITextField *)textField {
//Section 1.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
switch (textField.tag) {
case 1:
[defaults setObject:textField.text forKey:#"nameCellString"];
self.name = textField.text;
break;
default:
break;
}
[defaults synchronize];
}
EDIT: Changed to accommodate more cells.

You should use array of UIDictionary for your tableDataSourceArray Like:
step1)
NSArray *tableDataSourceArray = [[NSArray alloc]init];
NSMutableDictionary *cellData = [[NSMutableDictionary alloc]init];
[cellData setValue:#"" forKey:#"Name"];
...//so on
[tableDataSourceArray addObject:cellData];
cellData = nil;
repeat step1 as number of records you have.
Now in cellForRowAtIndexPath:
nameFieldTextField.tag = indexPath.row; //To store index of dataSourceArray
nameFieldTextField.text = [[tableDataSourceArray objectAtIndex:indexPath.row] valueForKey:#"Name"];
And at last in textFieldDidEndEditing:
NSMutableDictionary *cellDataDic = tableDataSourceArray objectAtIndex:textField.tag];
[cellDataDic setValue:textField.text forKey:#"Name"];
hope it will help you.

I think the easiest way to fix your problem is to create a new class for your cell (inherit from UITableViewCell) and add new property like customerTextField (UITextField). In constructor add new textfield but with CGRectZero. In method layoutSubviews you will assign CGRect for your textfield.
Generally speaking this approach will make your UIViewController cleaner (you will reduce number of checks for textfield state).

Related

UITextfield value successfully updated, but not shown in table

In my app rows are added to my TableView from a different view. When the user adds the rows the user is taken back to the TableView. The problem is that the text that was previously entered is no longer shown.
I am able to load it with an NSMutableDictionary but the user cannot see it. Any ideas on what I should do? what code I should add and where I should add it? Thanks a lot!
Here is code from a tableview method. I think the fix will go in here somewhere.
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath{
static NSString *CellIdentifier = #"Cell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.wtf = [[UITextField alloc]init];
NSUInteger count =0;
for (NSMutableDictionary *search in dataForAllRows){ //this just helps me pull the right data out of an array of NSMutableDictionary's
if ([search valueForKey:#"indexSection"] == [NSNumber numberWithInteger:(indexPath.section -1)]) {
if ([search valueForKey:#"indexRow"] == [NSNumber numberWithInteger:indexPath.row]) {
NSMutableDictionary *match = [dataForAllRows objectAtIndex:count];
[cell.wtf setText:[match objectForKey:#"wtf"]];
NSLog(#"%#",cell.wtf.text); // this outputs the correct value in the command line
}
}
count++;
}
}
}
Here is the code for my CustomCell.m
#import "CustomCell.h"
#implementation CustomCell
#synthesize wtf, cellPath;
- (void)awakeFromNib {
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(void)layoutSubviews{
wtf = [[UITextField alloc] initWithFrame:CGRectMake(7, 3, 65, self.contentView.bounds.size.height-6)];
self.wtf.delegate = self;
[wtf setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];
[wtf setAutocorrectionType:UITextAutocorrectionTypeNo];
[wtf setAutocapitalizationType:UITextAutocapitalizationTypeNone];
[wtf setBorderStyle:UITextBorderStyleRoundedRect];
wtf.textAlignment = NSTextAlignmentCenter;
wtf.keyboardType = UIKeyboardTypeNumberPad; //
[wtf setAutocapitalizationType:UITextAutocapitalizationTypeWords];
[wtf setPlaceholder:#"enter"];
[self.contentView addSubview:wtf];
}
Consider defining the cell with identifier #"Cell" in IB as a prototype row of the table. Then, use dequeueReusableCellWithIdentifier:forIndexPath: to retrieve the cell in cellForRowAtIndexPath. It's easier to understand what your cells will look like, and you can avoid some mistakes that are common when defining subviews in code.
Speaking of common mistakes, your code appears to present a couple: it doesn't frame the text field, nor does it add it as a subview of the cell. Both would explain not seeing the text field.
#williamb's advice is correct and necessary: only build the cell's subview's if they are absent, but the building of the cell is incomplete...
if (cell == nil) {
cell = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
UITextField *wtf = [[UITextField alloc]initWithFrame:CGRectMake(10,10,200,42];
[wtf setDelegate:self];
[cell addSubview:wtf];
cell.wtf = wtf;
}
As I mentioned in comment, a sectioned table ought to be supported by a 2D array. The outer array is an array of sections. Each section array is an array of dictionaries equal to the ones you're searching each time through this method, but pre-arranged so all that's done in cellForRowAtIndexPath is indexing into an array:
NSDictionary *d = self.myCorrectlyStructuredModel[indexPath.section][indexPath.row];
cell.wtf.text = d[#"wtf"];
It's not a big challenge to build this from what you have. Consider doing this right after you solve the text field problem. I (or others) can give you some advice -- if you need any -- about how to build that structure.
It looks like you are only setting the text value of your textfield if that cell does not exist and overriding your textfield instance to one that does not have a frame as #danh mentioned. What I believe you want to do is reuse the textfield once it is added to your cell's contentview and change what that textfield shows for each index path.
Try refactoring your cell code to be more like:
#implementation ExerciseCell
#pragma mark - Init
- (id)initWithStyle:(UITableViewCellStyle)style
reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style
reuseIdentifier:reuseIdentifier];
if (self)
{
wtf = [[UITextField alloc] initWithFrame:CGRectMake(7, 3, 65, 44)];
wtf.delegate = self;
[wtf setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];
[wtf setAutocorrectionType:UITextAutocorrectionTypeNo];
[wtf setAutocapitalizationType:UITextAutocapitalizationTypeNone];
[wtf setBorderStyle:UITextBorderStyleRoundedRect];
wtf.textAlignment = NSTextAlignmentCenter;
wtf.keyboardType = UIKeyboardTypeNumberPad;
[wtf setAutocapitalizationType:UITextAutocapitalizationTypeWords];
[wtf setPlaceholder:#"enter"];
[self.contentView addSubview:wtf];
}
return self;
}
and your tableview datasource class to be more like
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath{
static NSString *CellIdentifier = #"Cell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[cell.wtf setDelegate:self];
}
NSUInteger count = 0;
for (NSMutableDictionary *search in dataForAllRows){ //this just helps me pull the right data out of an array of NSMutableDictionary's
if ([search valueForKey:#"indexSection"] == [NSNumber numberWithInteger:(indexPath.section -1)]) {
if ([search valueForKey:#"indexRow"] == [NSNumber numberWithInteger:indexPath.row]) {
NSMutableDictionary *match = [dataForAllRows objectAtIndex:count];
[cell.wtf setText:[match objectForKey:#"wtf"]];
NSLog(#"%#",cell.wtf.text); // this outputs the correct value in the command line
}
}
count++;
}
}
}
Also do you mean to assign the the textField's delegate twice? Once in the cell and once in the tableview's datasource?
In order to load text into the UITextField in the CustomCell I added the following method
CustomCell.m
-(void)viewMyCellData{
//here I can set text to my textfield
wtf.text = #"Desired Text"; //this will read in every wtf textfield in the table
//getting the right text from an array will be asked in another question that I will post
//in a comment to this answer
}
Next we call this using [self viewMyCellData]
at the end of our
-(void)layoutSubviews method which is also in CustomCell.m

How to redraw UITableViewCells automatically given different sorting parameters

I have a UITableViewController called HighScoreViewController that possesses UITableViewCells that are each individual HighScore objects.
When I press the segmented control at the top I want to resort the TableCells immediately. However, currently my sort only works by dragging around so that the cells are off-screen causing the (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath to be called again (which resorts the individual cell according to the score, duration, or date).
I tried to create a method that would be called in my segmented control action that would remove and add the View to redraw the cells. When that didn't work I tried redrawing each cell manually but I realized that it would be a extremely complicated as I would have to monitor which scores had already been sorted in the View and what scores were sorted in the Data Source. I also tried setNeedsDisplay.
How can I resort the UITableViewCells immediately after pressing the segmented control?
This is my action outlet for the segmented Control
- (IBAction)changeSort:(id)sender {
NSLog(#"changing Sort");
// Sorted by score
if (self.sortingButton.selectedSegmentIndex == SORT_BY_SCORE){
[self sortHighScoresByScore];
}else if (self.sortingButton.selectedSegmentIndex == SORT_BY_DURATION){// sorted by duration
[self sortHighScoresByDuration];
}else if (self.sortingButton.selectedSegmentIndex == SORT_BY_DATE){// sorted by last time played
[self sortHighScoresByDate];
}else{
NSLog(#"HighScoreViewController, changeSort else != 0,1,2");
}
}
And this is my cell method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"HighScoreCell" forIndexPath:indexPath];
NSLog(#"inside TableView");
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"HighScoreCell"];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *playingCardHighScores = [defaults objectForKey:#"playingCardHighScores"];
NSMutableArray *setCardHighScores = [defaults objectForKey:#"setCardHighScores"];
// Decode High Scores arrays
playingCardHighScores = [self decodeEncodedArray:playingCardHighScores];
setCardHighScores = [self decodeEncodedArray:setCardHighScores];
/* Will need to set the left and right side to two different scores or add some kind of slider*/
HighScore *hs = playingCardHighScores[indexPath.row];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(55, 4, 260, 20)];
label.font = [UIFont boldSystemFontOfSize:15.0];
label.tag=25;
UILabel *detailLabel = [[UILabel alloc] initWithFrame:CGRectMake(25, 25, 260, 15)];
detailLabel.adjustsFontSizeToFitWidth = YES;
detailLabel.tag=30;
NSString *score = [NSString stringWithFormat:#"Score:%ld",(long)hs.score];
NSString *duration = [NSString stringWithFormat:#",Duration:%.2f",hs.secondsPlayed];
NSString *datePlayed = [NSString stringWithFormat:#",datePlayed:%#",hs.datePlayed];
NSString *combination = [score stringByAppendingString:[duration stringByAppendingString:datePlayed]];
detailLabel.text = combination;
[cell.contentView addSubview:label];
[cell.contentView addSubview:detailLabel];
// Should change depending on what selector is picked
NSString *strScore;
NSDate *date;
switch (self.sortingButton.selectedSegmentIndex) {
case SORT_BY_SCORE:
strScore = [NSString stringWithFormat:#"Score: %ld",(long)hs.score];
break;
case SORT_BY_DURATION:
strScore = [NSString stringWithFormat:#"Duration: %.2f seconds",hs.secondsPlayed];
break;
case SORT_BY_DATE:
date = hs.datePlayed;
break;
default:
break;
}
// if the string exists
if (strScore){
cell.textLabel.text = strScore;
}else{
cell.textLabel.text = [date description];
}
return cell;
}
You'll need to call [self.tableView reloadData] in your segmented control IBAction to get all the cells on screen to be recreated.
Alternatively if you want to be able to specify stock animation, you can call reloadSections:withRowAnimation: on your table view

How to get UITextField (subview to UITableViewCell) text value when tableview cell became invisible

I created a custom UITableViewCell class that embedded a UITextfield to each cell, in the addItemTableViewController, I want to get text values within all UITextField-embededd cells and create a new model object, but I'm running into a problem:
cellForRowAtIndexPath returns nil for invisible cells, after I scrolled down to the buttom of my tableview then hit the Add button, the first a few rows' textField text value became null.
Is there anyway I can fix this? I've been Googlging for hours and still not find a answer for it.
Here's my addItemTableViewController code:
- (IBAction)doneAdd:(UIBarButtonItem *)sender {
[self.delegate addItem:[self newItem]];
}
- (NSMutableArray *)newItem
{
NSMutableArray *newItem = [[NSMutableArray alloc] init];
for (int i = 0; i < [_appDelegate.title count]; i ++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
UPFEditableUITableViewCell *cell = (UPFEditableUITableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
NSLog(#"%#", cell.editField.text);
//[newItem addObject:cell.editField.text]; //this does not work as null cannot be added into a array
}
NSLog(#"%#", newItem);
return newItem;
}
Here's my custom UITableViewCell class implementation
#import "UPFEditableUITableViewCell.h"
#implementation UPFEditableUITableViewCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.editField = [[UITextField alloc] initWithFrame:CGRectZero];
[self.contentView addSubview:self.editField];
}
return self;
}
- (void)layoutSubviews
{
if ([self.detailTextLabel.text length] == 0) {
self.detailTextLabel.text = #" ";
}
[super layoutSubviews];
// place the edit field in the same place as the detail text field, give max width
self.editField.frame = CGRectMake(self.detailTextLabel.frame.origin.x, self.detailTextLabel.frame.origin.y, self.contentView.frame.size.width-self.detailTextLabel.frame.origin.x, self.detailTextLabel.frame.size.height);
}
- (void)showEditingField:(BOOL)show
{
self.detailTextLabel.hidden = YES;
self.editField.text = self.detailTextLabel.text;
}
#end
I think made a fundamental mistake, have my view talks with the model layer, what a lesson learned...
anyway, I managed to work out a solution, in short, here's what I did:
made cell as the delegate of the UITextField
implemented textFieldDidChange, to capture textField changes, once there's a change, submit the changed content to the model
And here's the code:
in the cellForRowAtIndex:
[cell.editField addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
cell.editField.delegate = self;
and here's the code for the textFieldDidChange:
- (void)textFieldDidChange :(UITextField *)theTextField
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
[self.item removeObjectAtIndex:indexPath.row];
[self.item insertObject:theTextField.text atIndex:indexPath.row];
}
This is not a problem.The cell are dequeud and reused whenever new cells are created.Hence while scrolling the tableview at the top they become null and the new cells are created with the same identifier.
For your problem you will need to store the value of textfield's value into a dictionary.For this you will need to save it at the time you are dequeing the cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellReuseIdentifier = #"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellReuseIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellReuseIdentifier];
}else{
NSLog(#"text is %#",cell.textLabel.text);
for (UIView *v in cell.contentView.subviews) {
if ([v isKindOfClass:[UITextField class]]) {
UITextField *textField = (UITextField *)v;
[myDictionary setObject:textField.text forKey:indexPath]; // declare myDictionary in the interface first.This will also prevent the values from duplicating
NSLog(#"%#",myDictionary);
}
}
}
return cell;
}
To get value from UITextField you can set the delegate on your ViewController. Then you should implement textField:shouldChangeCharactersInRange:replacementString: where you can update NSString value.
The second solution might be keeping reference to the each cell in NSMutableArray.
Anyway you try to avoid calling cellForRowAtIndexPath: from table view controller.
You should always try to save the data in model classes and use the array of these model class instances to load the table. So that you don't need the tableCells to get the data after that. The datas are always to be fetched from models and not the UIs (TableCells in this case).
You might be loading the tablecell initially using an arra,y. If so, use that array to create the model class objects you mentioned instead of the tablecells.

Text Field on Top of Button - iPhone

So I'm trying to figure out ideas for my registration page in xCode -- something like this: http://weswilliams.me/wp-content/uploads/2011/06/IMG_2525-e1307910945329.png
At any rate, I can't figure out what objects they are using to achieve this display. It looks like a TextField on top of a Button? If it is, I can never get the Text Field to sit on top, it always falls behind the button, thus making it invisible.
Any tips or suggestions?
This is not a textfield on the button. Actually it is text box inside a table view. You have to do the following :
Take a table view on the nib.
Create the outlet and set the delegate and datasource.
Then add the following code to your .m file.
try this one
before this set the number of rows the table view has.
- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:#"Cell"];
if( cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"] autorelease];
cell.textLabel.text = [[NSArray arrayWithObjects:#"First",#"Second",#"Third",#"Forth",#"Fifth",#"Sixth",#"Seventh",#"Eighth",#"Nineth",#"Tenth",nil]
objectAtIndex:indexPath.row];
if (indexPath.row % 2) {
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 200, 21)];
textField.placeholder = #"Enter Text";
textField.text = [inputTexts objectAtIndex:indexPath.row/2];
textField.tag = indexPath.row/2;
textField.delegate = self;
cell.accessoryView = textField;
[textField release];
} else
cell.accessoryView = nil;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
Or you can see this link See this answer on SO
Thats a basic grouped UITableView. Read up on Apple docs. There are a ton of tutorials on that too.

Access to UITextField in CellForRowAtIndexPath

i´m adding a UITextField on a 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];
}
myLoc = [[UITextField alloc] initWithFrame:CGRectMake(35, 10, 250, 40)];
myLoc.adjustsFontSizeToFitWidth = YES;
myLoc.textColor = [UIColor blackColor];
myLoc.textAlignment = UITextAlignmentCenter;
myLoc.placeholder = #"Enter Location";
myLoc.returnKeyType = UIReturnKeyDone;
myLoc.autocorrectionType = UITextAutocapitalizationTypeNone;
myLoc.tag = indexPath.row;
myLoc.delegate = self;
[myLoc setEnabled:YES];
[cell addSubview:myLoc];
return cell;
}
and in the textFieldShouldReturn i would write the text from the textfield in a mutable array, and store in nsuserdefaults.
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[myLoc resignFirstResponder];
[locationArray addObject:textField.text];
locName = [NSUserDefaults standardUserDefaults];
[locName setObject:locationArray forKey:#"textName"];
[locName synchronize];
NSLog(#"Done pressed %#",myLoc.text);
return YES;
}
...but the myLoc.text is always null
any ideas for me?
In the delegate method, don't use myLoc to reference the textField, but use the actual textField pointer provided as parameter of the function. This one should actually point to the correct textfield and thus textField.text should have the correct value.
On a side note: Where do you define myLoc? It looks like you're trying to set a property on your viewcontroller. This way you'll always overwrite the property. For this you don't need a property at all, so just define myLoc locally in the function scope like UILabel *myLoc
You're better off creating your own custom UITableViewCell. You can see how to create one here:
tutorial
Trying to tack on to the existing UITableViewCell is difficult at best and impossible at worst. You're better off with custom cells.
Your text should never be NULL, since its an NSString. Are you sure you're talking about the text from the text field?
What outputs when you add NSLog(#%"#", textField.text); to your shouldReturn method?
Are you sure that you have typed in the text field? Also, even without typing, you should be getting #"" instead of nil.

Resources