Change the text of the UITextField right before editing when using a custom UITableViewCell
I have a strange problem here. I have a UITableView using custom UITableViewCells. Everything works as expected except for that specific issue.
Here's the script:
I need to remove the "$" character in the UITextField before starting editing. This is done using the method textFieldShouldBeginEditing:
.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
LifeEarningsLineItemTableViewCell *cell = (LifeEarningsLineItemTableViewCell *)[self tableViewCellContainingObject:textField inTableView:self.lifeEarningsTableView];
if (textField == cell.itemAmount) {
/*Remove currency symbol for editing.*/
NSString *currencySymbol = [self.currencyFormatter currencySymbol];
NSMutableString *mutableText = [NSMutableString stringWithString:textField.text];
[mutableText replaceOccurrencesOfString:currencySymbol withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [mutableText length])];
textField.text = mutableText;
}
return YES;
}
Here's the problem:
- Between different lines, going from textField1 to textField2 (on another line), "$" is removed, this is GOOD .
- In the same line , moving from textField1 to textField2, the "$" is removed not , it's BAD .
Why is "$" not removed on the same line, but executed on different lines?
Here's a visual representation of the problem:
[EDIT ... Addition]
I am getting these logs with these streams:
SHOULD START ..... Line: 0, Label: 0
SHOULD START ..... Line: 0, Label: 1
DID END ..... Line: 0, Label: 0
DID END ..... String : 0, tag: 1
SHOULD START ..... Line: 0, Label: 0
SHOULD START ..... Row: 1, Label: 1
DID END ..... Line: 0, Label: 0
DID END ..... String : 1, tag: 1
Also, here's the method tableViewCellContainingObject:inTableView:tableView
:
- (UITableViewCell *)tableViewCellContainingObject:(UIView *)view inTableView:(UITableView *)tableView {
CGPoint objectRectInTableViewCoordinates = [tableView convertPoint:view.bounds.origin fromView:view];
NSIndexPath *cellIndexPath = [tableView indexPathForRowAtPoint:objectRectInTableViewCoordinates];
return [tableView cellForRowAtIndexPath:cellIndexPath];
}
And the method textFieldDidEndEditing
:
- (void)textFieldDidEndEditing:(UITextField *)textField {
LifeEarningsLineItemTableViewCell *cell = (LifeEarningsLineItemTableViewCell *)[self tableViewCellContainingObject:textField inTableView:self.lifeEarningsTableView];
LifeEarningsLineItem *lifeEarningsLineItem = [self.lifeEarningsFetchedResultsController objectAtIndexPath:[self.lifeEarningsTableView indexPathForCell:cell]];
if (textField == cell.itemAmount) {
NSNumber *absInteger = [NSNumber numberWithInteger:abs([textField.text integerValue])];
textField.text = [self.currencyFormatter stringFromNumber:absInteger];
lifeEarningsLineItem.amount = absInteger;
[self sumAmountsAndDisplay];
} else if (textField == cell.itemName) {
lifeEarningsLineItem.name = textField.text;
}
}
source to share
I think your decision (decoupling FRC while editing) might be a little harsh and might have unintended consequences. Here are some alternative suggestions. I am guessing that the problem is caused by reloading the table you are editing after you have finished editing the first field in the cell.
- Don't store the currency symbol in your model, add it to the display text in cellForRowAtIndexPath if the textbox is not editable. When your textbox starts editing, set its text to a value directly from the model. You don't need to do anything at the end of the edit, as the reload will add the currency symbol to you.
- If you don't want to change the model, you can do something like this anyway - in cellForRowAtIndexPath, remove the currency symbol if the cell is editing.
- Save the pointer path to the currently edited line and conditionally ignore changes to that line in the FRC delegate method.
source to share
Ok I figured out the problem ... it was the goth darn delegation methods NSFetchedResultsController
, specifically the change type NSFetchedResultsChangeUpdate
. This isn't the first time I've NSFetchedResultsController
walked all over my table. I had to remember that it NSFetchedResultsController
doesn't work very well with custom changes.
So, this is how I solved the problem (but I am still afraid that it all might crash):
Due to the order of events ...
SHOULD BEGIN.....Row:0, Tag:0
SHOULD BEGIN.....Row:0, Tag:1
DID END.....Row:0, Tag:0
DID END.....Row:0, Tag:1
... I couldn't just use a property BOOL
to tell the textbox is in edit mode (the order of events should be BEGIN-> END-> BEGIN-> END).
So I created a property: @property (nonatomic, strong) NSMutableSet *stackOfEditingTextFields;
Then at the beginning of the method, textFieldShouldBeginEditing:
I added:
/*Add text field to stack of editing text fields and disable the fetched results controller delegate.*/
[self.stackOfEditingTextFields addObject:textField];
self.lifeEarningsFetchedResultsController.delegate = nil;
Then at the end of the method, textFieldDidEndEditing:
I added:
/*Remove text field from stack of editing text fields. If stack count is 0, reengage the fetched results controller delegate.*/
[self.stackOfEditingTextFields removeObject:textField];
if ([self.stackOfEditingTextFields count] == 0) self.lifeEarningsFetchedResultsController.delegate = self;
If there is a better suggestion or some unexpected errors that I can't see, I'm all ears.
Thanks for the help lnafziger , helping me work through her and offering different angles (I + 1'd your comments).
source to share