Note that there are some explanatory texts on larger screens.

plurals
  1. POUITableView visibleCell - Will non-visibleCell be recreated with tableView:cellForIndexPath:
    primarykey
    data
    text
    <p><strong>Background</strong></p> <p>I have a class with a UITableView ivar named _tableView. The class implements UITableViewDatasource and UITableViewDelegate _tableView. The UITableView cells are instances of FormTableCell. FormTableCell is a subclass of UITableViewCell, with a UILabel and a UITextField. On the class I have a property called textFieldDelegate. When tableView:cellForIndexPath: is called the current textFieldDelegate is assigned to the textField property of the returned cell. Also when the classes textFieldDelegate is modified I want to update the cells textfield's delegate. I have come up with three ways of doing this, but don't know the best way. </p> <ol> <li>Update the delegate of each visible cell with the new textFieldDelegate.</li> <li>Iterate through all the cells and assign the new textFieldDelegate</li> <li>reload the tableViews data.</li> </ol> <p>Option 1 is good, but it assumes tableView:cellForIndexPath will be called before displaying any cells not in the tableView's visibleCells array. If this does not happen then different cells could have different delegates and that's not what I want.</p> <p>Option 2 is the worst because it only works well for small numbers of cells, I would hope FormTables would always have small numbers of cell, but I never know.</p> <p>Option 3 trumps Option 1 if my assumption that tableView:cellForIndexPath: will be called before displaying non-visible cells is invalid and it trumps Options 2 because it handles tables with lots of cells.</p> <p><strong>Question</strong></p> <p>Which is the best option and is my assumption that tableView:cellForIndexPath: will be called before a non-visible cell becomes visible or is interacted with incorrect?</p> <p><strong>Code</strong></p> <pre><code>- (void)setTextFieldDelegate:(id&lt;UITextFieldDelegate&gt;)textFieldDelegate { if(_textFieldDelegate != textFieldDelegate) { _textFieldDelegate = textFieldDelegate; //Update _textFieldDelegate for all visible cells. //!DEV: Assuming non-visible cells will be recreated with tableView:cellForIndexPath: for (FormTableCell *cell in [_tableView visibleCells]) { [[cell textField] setDelegate:_textFieldDelegate]; } //!DEV: This will potentially generate memory issues for a large number of cells for(NSUInteger i = 0; i &lt; kNumberOfFields; ++i) { NSIndexPath *indexPath = [NSIndexPath indexPathForItem:(NSInteger)i inSection:0]; FormTableCell *cell = (FormTableCell*)[_tableView cellForRowAtIndexPath:indexPath]; [[cell textField] setDelegate:_textFieldDelegate]; } //!DEV: Maybe this is the best method, but it requires the recreation of visibleCells. [_tableView reloadData]; } } </code></pre> <p><strong>Final Status</strong></p> <p>So this is what I ended up doing. I implemented a Decorated Delegate(?) </p> <pre><code>- (void)setTextFieldDelegate:(id&lt;UITextFieldDelegate&gt;)textFieldDelegate { if(_textFieldDelegate != textFieldDelegate) { _textFieldDelegate = textFieldDelegate; } } #pragma mark - UITextFieldDelegate Implementation //This class forwards UITextFieldDelegate methods on to _textFieldDelegate, if implemented. //Provides default functionality is not implemented. - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { if([_textFieldDelegate respondsToSelector:@selector(textFieldShouldBeginEditing:)]) { return [_textFieldDelegate textFieldShouldBeginEditing:textField]; } //implicit else return YES; } - (void)textFieldDidBeginEditing:(UITextField *)textField { //Setup _closeKeyboardButton behind _tableView //view::closeKeyboardButton (_closeKeyboardButton) NSAssert(_closeKeyboardButton == nil, @"!DEV: Thought _closeKeyboardButton would always be nil here."); if(_closeKeyboardButton != nil) { [_closeKeyboardButton removeFromSuperview]; _closeKeyboardButton == nil; } CGRect closeKeyboardFrame = {CGPointZero, [self frame].size}; UIButton *closeKeyboardButton = [UIButton buttonWithType:UIButtonTypeCustom]; [closeKeyboardButton setFrame:closeKeyboardFrame]; [closeKeyboardButton addTarget:self action:@selector(_closeKeyboardButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; [self insertSubview:closeKeyboardButton belowSubview:_tableView]; _closeKeyboardButton = closeKeyboardButton; if([_textFieldDelegate respondsToSelector:@selector(textFieldDidBeginEditing:)]) { [_textFieldDelegate textFieldDidBeginEditing:textField]; } } - (BOOL)textFieldShouldEndEditing:(UITextField *)textField { if([_textFieldDelegate respondsToSelector:@selector(textFieldShouldEndEditing:)]) { return [_textFieldDelegate textFieldShouldEndEditing:textField]; } //implicit else return YES; } - (void)textFieldDidEndEditing:(UITextField *)textField { if([_textFieldDelegate respondsToSelector:@selector(textFieldDidBeginEditing:)]) { [_textFieldDelegate textFieldDidBeginEditing:textField]; } //Tear down _closeKeyboardButton NSAssert(_closeKeyboardButton != nil, @"!DEV: Thought _closeKeyboardButton would always exist here."); [_closeKeyboardButton removeFromSuperview]; _closeKeyboardButton = nil; } - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { if([_textFieldDelegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]) { return [_textFieldDelegate textField:textField shouldChangeCharactersInRange:range replacementString:string]; } //implicit else return YES; } - (BOOL)textFieldShouldClear:(UITextField *)textField { if([_textFieldDelegate respondsToSelector:@selector(textFieldShouldClear:)]) { return [_textFieldDelegate textFieldShouldClear:textField]; } //implicit else return YES; } - (BOOL)textFieldShouldReturn:(UITextField *)textField { if([_textFieldDelegate respondsToSelector:@selector(textFieldShouldReturn:)]) { return [_textFieldDelegate textFieldShouldReturn:textField]; } //implicit else return NO; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload