Reputation: 279
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
Upvotes: 2
Views: 4907
Reputation: 279
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:
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];
}
Upvotes: 3
Reputation: 4249
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;
}
Upvotes: 1
Reputation: 1599
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.
Upvotes: 0
Reputation: 2252
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.
Upvotes: 0