views:

263

answers:

2

I have a problem and lots of difficulty finding a solution, even if I would assume lots of people should have had similar issues. Hopefully someone can help me.

I've created a Settings screen for my application using a UITableView. A NSArray is used to configure the controls I intend to display. The array looks like this:

[self setControlArray:[NSArray arrayWithObjects:
                 [NSArray arrayWithObjects:
                  [NSDictionary dictionaryWithObjectsAndKeys:@"Username", @"text", nil], 
                  [NSDictionary dictionaryWithObjectsAndKeys:@"Password", @"text", nil], 
                  [NSDictionary dictionaryWithObjectsAndKeys:@"Server", @"text", nil], 
                  [NSDictionary dictionaryWithObjectsAndKeys:@"Port", @"text", nil], 
                  [NSDictionary dictionaryWithObjectsAndKeys:@"Use SSL", @"text", nil], 
                  nil],
                 nil]];

For every item in the array I create a control in the following manner (in ViewDidLoad):

// TextField: USERNAME
username = [[UITextField alloc] initWithFrame:CGRectMake(99.0, 15.0, 190.0, 18.0)];
[self layoutTextField:username withFont:[UIFont systemFontOfSize:13.0] keyboardType:UIKeyboardTypeAlphabet placeholder:@"Username" clearsOnBeginEditing:NO];
[username setText:[Settings sipUser]];          

Finally every control is added to the UITableView using the [tableView:cellForRowAtIndexPath] message:

static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

    NSString *label = [[[controlArray objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]] objectForKey:@"text"];
    [[cell textLabel] setText:label];

    // TextField: USERNAME
    if ([[[[controlArray objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]] objectForKey:@"text"] isEqual:@"Username"]) {
        [[cell contentView] addSubview:username];
}
return cell;

Every time one of the controls in my array gets out of focus (disappears from screen) because of the scrolling the controls that were out of sight get reordered. I would assume the controls are released and recreated when scrolling back in sight, but whatever I try I can't find a solution for this problem.

+2  A: 

Your problem is, you're using [tableView dequeueReusableCellWithIdentifier:CellIdentifier] which can actually return a non-nil cell (e.g. with one of the other buttons) and then you'll just return it, making it seem they're rearranging (almost) randomly.

You have to make an else branch in the code and, if the dequeued reusable cell isn't nil:

  • remove any buttons from the cell
  • add the button you need
  • set the cell's label

and then return it.

Adam Woś
A: 

Thanks mate, your suggestion worked for me. For any people interested my [tableView:cellForRowAtIndexPath:] message looks like the following now:

static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

    NSString *label = [[[controlArray objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]] objectForKey:@"text"];
    [[cell textLabel] setText:label];

    // TextField: USERNAME
    if ([[[[controlArray objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]] objectForKey:@"text"] isEqual:@"Username"]) {
        [[cell contentView] addSubview:username];
    }
} else {
    NSString *label = [[[controlArray objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]] objectForKey:@"text"];
    [[cell textLabel] setText:label];

    // TextField: USERNAME
    if ([[[[controlArray objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]] objectForKey:@"text"] isEqual:@"Username"]) {
        [username removeFromSuperview];
        [[cell contentView] addSubview:username];
    }
}  
return cell;
Wolfgang Schreurs