2

If I have a lot of accounts in a UITableView. The UITextFid text which I edited in a first cell is resetting when I scroll the UITableView. This is happening because of cell reusability. I am not setting my UITextFid text in UITableView at cellForRow at Indexpath. I am doing it in custom cell view due to other implementation.

Can you please guide me.

STTableViewCell *cell;
cell =  [tableView dequeueReusableCellWithIdentifier:@"STTableViewCell"];

if (cell == nil)
{
    cell = [[STTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"STTableViewCell"];
}

cell.accountNameTxtField.delegate = self

// Fetching the URL from Array at index of indexpath.row
OTPAuthURL *url = [self.authURLs objectAtIndex:indexPath.row];

// Sending the generated authURl and token description to custom STTableViewCell to load the data in a tableView
[(STTableViewCell *)cell setAuthURL:url withtokenDesc:nil];

return cell;
Anoop Nyati
  • 339
  • 2
  • 11
Sadik
  • 91
  • 6

5 Answers5

1

You will need to maintain an array with number of objects equal to number of items in tableview. Every textfield should have a tag equal to indexPath.row of that row. e.g:

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
           let cell:CustomUITableViewCell = tableView.dequeueReusableCell(withIdentifier: "customCell")! as CustomUITableViewCell
                cell.textfield = indexPath.row
                cell.textfield.delegate = self
                cell.textfield.text = arrayTemp[indexPath.row] as String
}
    }

Using delegate methods of textfield you will have

   public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool{
     arrary[textfield.tag] = textfield.text
}

In textfield delegate method you need to save the text in temp array at index equivalent to tag of textfield

pankaj
  • 7,878
  • 16
  • 69
  • 115
0

You need to store the text that was entered as its entered or as it loses focus, once the cell is recycled the information will be lost. use the delegate callback from the textfield textfieldDidEndEditing Then when the cell comes back into view you need to check if text was stored before and repopulate it.

Can also try this method for listening for editing events

Community
  • 1
  • 1
Fonix
  • 11,447
  • 3
  • 45
  • 74
  • If i store value in textfieldDidEndEditing like- self.accountNameTxtField.text = authURL.name;. When my table view is going from editing mode to normal mode that value value is reflecting in tbale view. Though i am not storing the vlaue in my keychain with done bar button action. – Sadik Jan 19 '17 at 09:06
  • yeah thats not quite the storing i mean, you need to store it somewhere other than the textfield itself, cause that `self.accountNameTxtField.text` is going to be reset when the cell gets recycled (assuming that this is within the cell), you need to store it outside of the cell somehow, which only you will know how best to do that cause i dont know how your program is structured – Fonix Jan 19 '17 at 09:20
0

DO set the value in cellForRowAtIndexPath. That is what it is made for. Doing so all of this re-use stuff simply works like charme.

What I do with custom views is this: In my custom view class I create some bind(MyObject myObject) method (or bind:(MyObject*)myObject respecitvely). The bind method receives the object to be displayed as parameters (or a number of them). The bind method then does all the custom stuff in order to display the object within the cell, so that the view controller (having implemented cellForRowAtIndexPath) keeps free from any custom view related stuff, with the exception of the bind method.

And I call this bind method every time in cellForRowAtIndexPath.

Hermann Klecker
  • 14,039
  • 5
  • 48
  • 71
0

It will look like everything is working as expected - while that cell is still displayed. But you're reusing the cells every time one disappears off the display, so the information is lost.

You need to separate your data model and display - if all you have is text for one field, then create an array of String (myTableData : [String]), and in cellForRowAt set the textfield to myTableData[indexPath.row]

If you need to populate more than one field in the table, then define a struct (or class) with what you need, and use an array of that to populate the table

Russell
  • 5,436
  • 2
  • 19
  • 27
0

Elaborating Pankaj's answer.

You can update your text setting method something like this

- (void)setAuthURL:(OTPAuthURL *)authURL withtokenDesc:(NSString *)tokenDesc andTag:(NSInteger)tag
{
    self.accountNameTxtField.tag = tag;
    self.accountNameTxtField.text = authURL.name;
}

From cellForRowAtIndexPath method, instead of simply setting text, also set tag with it.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    STTableViewCell *cell;
    cell =  [tableView dequeueReusableCellWithIdentifier:@"STTableViewCell"];

    if (cell == nil)
    {
        cell = [[STTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"STTableViewCell"];
        cell.accountNameTxtField.delegate = self
    }

    // Fetching the URL from Array at index of indexpath.row
    OTPAuthURL *url = [self.authURLs objectAtIndex:indexPath.row];

    // Sending the generated authURl and token description to custom STTableViewCell to load the data in a tableView, and setting unique tag for textfield
    [(STTableViewCell *)cell setAuthURL:url withtokenDesc:nil andTag:indexPath.row];

    return cell;
}

Implement UITextFieldDelegate method

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    //Printing log to check tag
    NSLog(@"Tag = %ld",textField.tag);

    //Update the original array
    self.authURLs[textField.tag] = textField.text;

    //Dismiss keyboard
    [textField resignFirstResponder];

    return YES;
}

Hope this helps!

Anoop Nyati
  • 339
  • 2
  • 11