开发者

UITableView with custom UITableViewCells mixing content when scrolling

I have an heterogeneous tableView with an entire section made up of UITableViewCells with a UITextField control on each one's contetView. The problem is that I see text written in textfields being mixed when I scroll.

I've seen many times before this problem and though it's deprecated I solved by assigning a different cellIdentifier for every kind of cell.

What's different now is that I'm creating cells dynamically and depending on the answer of the server the section of the table might have zero or more custom cells (the one that has the textField).

Now, it's interesting to see that textfiled's properties like the placeholder is persistent throughout the scrolls but the text I write is not persistent at all, the text changes it's position...

I have a video here so you can see what I mean.

The code I use is like the following:

    // Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";
    NSString *varCellID = [NSString stringWithFormat:@"%i_VarCellID", (indexPath.row + 7891)];

    if (indexPath.section == 0) {
           UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
            [self configureCellViews:cell indexPath:indexPath];
        }
        [self configureCellContent:cell indexPath:indexPath];
        return cell;
    }
    else if (indexPath.section == 1) {
开发者_如何转开发              UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
            [self configureCellViews:cell indexPath:indexPath];
        }
        [self configureCellContent:cell indexPath:indexPath];
        return cell;
    }
    else {
            UITableViewCell *varCell = [tableView dequeueReusableCellWithIdentifier:varCellID];

        if (varCell == nil) {
            varCell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:varCellID] autorelease];
            varCell.selectionStyle = UITableViewCellSelectionStyleNone;
            [self configureCellViews:varCell indexPath:indexPath];
        }
        [self configureCellContent:varCell indexPath:indexPath];
        return varCell;
    }
}

I know it's not elegant but woked before. Except for the dinamically created cell identifier that is one of my (desperate) attempts to keep individual contents on each textField.

Here's how I create cell's views and content:

#pragma mark -
#pragma mark  ConfigureCellcontent

- (void)configureCellViews:(UITableViewCell *)cell indexPath:(NSIndexPath *)indexPath {

    NSArray *aSection = [sections objectAtIndex:indexPath.section];
    NSDictionary *aField;
    int varformatid;

    if (indexPath.section == 0) {

        cell.detailTextLabel.textAlignment = UITextAlignmentLeft;
    }
    else if (indexPath.section == 1) {

        cell.detailTextLabel.textAlignment = UITextAlignmentLeft;
    }
    else {

        aField = [aSection objectAtIndex:indexPath.row];
        varformatid = [[aField valueForKey:@"varformatid"] intValue];
        NSArray *aSection = [sections objectAtIndex:indexPath.section];
        NSLog(@"format id %@", [[aSection objectAtIndex:0] valueForKey:@"varname"]);

        fieldLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 7, 100, 30)];
        fieldLabel.tag = 1234;
        fieldLabel.textAlignment = UITextAlignmentLeft;
        fieldLabel.font = [UIFont boldSystemFontOfSize:14];
        fieldLabel.adjustsFontSizeToFitWidth = YES;
        [cell.contentView addSubview:fieldLabel];

        theTextField = [[UITextField alloc] initWithFrame:CGRectMake(130, 12, 170, 30)];
        theTextField.textColor = kAnswersTextColor;
        theTextField.returnKeyType = UIReturnKeyDone;
        theTextField.tag = indexPath.row + 101;
        theTextField.adjustsFontSizeToFitWidth = YES;
        theTextField.delegate = self;


        if(varformatid == 6 || varformatid == 7 || varformatid == 8) {
            // use number pad input
            theTextField.keyboardType = UIKeyboardTypeNumberPad;
            [cell addSubview: theTextField];
            [theTextField release];
        }
        else if(varformatid == 4) {
            // use date
        }
        else if(varformatid == 17 || varformatid == 18) {
            // use pull down, elements of pull down are in XML
        }
        else if(varformatid == 20) {
            theSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(120, 8, 100, 30)];
            theSwitch.selected = YES;
            [cell.contentView addSubview:theSwitch];
        }
        else {
            // use input string
            [cell addSubview: theTextField];
            [theTextField release];
        }       
    }

}

- (void)configureCellContent:(UITableViewCell *)cell indexPath:(NSIndexPath *)indexPath {

    NSArray *aSection = [sections objectAtIndex:indexPath.section];
    NSString *aField;


    if (indexPath.section == 0) {
        aField = [[aSection objectAtIndex:0] valueForKey:@"SetDate"];
        cell.textLabel.text = @"Set Date";
        cell.detailTextLabel.text = aField;
    }
    else if (indexPath.section == 1) {
        aField = [[aSection objectAtIndex:0] valueForKey:@"SetType"];
        cell.textLabel.text = @"Set Type";
        cell.detailTextLabel.text = aField;
    }

    else {

        aField = [[aSection objectAtIndex:indexPath.row] valueForKey:@"varname"];
        if ([[[aSection objectAtIndex:indexPath.row] valueForKey:@"varrequired"] isEqualToString:@"yes"]) {
            [(UITextField *)[cell viewWithTag:indexPath.row + 101] setPlaceholder: @"Required"];
        }
        else [(UITextField *)[cell viewWithTag:indexPath.row + 101] setPlaceholder: @"Optional"];
        [(UILabel *)[cell.contentView viewWithTag:1234] setText: aField];

    }
}

Finally I ask your help to find at least one better approach. Thanks in advance.


Your configureCellContent seems broken. So you either didn't update your internal data structure with the typed text (you probably want to do that on every text change), or you miss to fill in the correct values in configureCellViews.

Sidenote: You shouldn't dequeue two cells at the top. Just dequeue the right one! I.e. put that into the if sections.


I've encountered this before. I believe it's because UITableViewCells are released when not visible to reduce memory consumption. When you scroll back up, you'll get a newly dequeued instance for that cell.

You'll need to save the state of the cell somewhere to re-initialise it when it returns into view. When you save is entirely up to you - when your UITextField loses focus, or when the field is changed in any way.


I don't know if this is the solution you are attending but you can just modify the CellIdentifier and make it unique.

NSString *CellIdentifier = [NSString stringWithFormat:@"Cell %d",indexPath.row];


NSString *CellIdentifier = [NSString stringWithFormat:@"Cell %d",indexPath.row]; in place of static NSString *CellIdentifier = @"Cell";

is the solution for mixing of rows in case of fast scrolling.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜