自定义UITableViewCell重绘问题

Chu*_*uck 9 iphone objective-c uitableview

我有一个自定义的UITableView单元格,我已经添加了一个文本框进行编辑,根据编辑模式显示和隐藏.我还尝试添加一条显示编辑时的垂直线,并且它会这样做,但我遇到了一些绘图问题.我刚刚添加了绿色复选标记rightView以开始处理输入验证反馈,我看到了类似的问题.

这是单元格的代码,也是我的cellForRowAtIndexPath的一部分.

#import <UIKit/UIKit.h>

    @interface EditableCellStyle2 : UITableViewCell {
        CGRect editRect;
        UITextField *editField;
        UIView *lineView;
    }

    @property (nonatomic, readonly, retain) UITextField *editField;
    @property (nonatomic, readonly, retain) UIView *lineView;

    @end
Run Code Online (Sandbox Code Playgroud)
#import "EditableCellStyle2.h"


@implementation EditableCellStyle2

@synthesize editField;
@synthesize lineView;


- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {

    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code.
        editRect = CGRectMake(83, 12, self.contentView.bounds.size.width-83, 19);

        editField = [[UITextField alloc] initWithFrame:editRect];
        editField.font = [UIFont boldSystemFontOfSize:15];
        editField.textAlignment = UITextAlignmentLeft;
        editField.textColor = [UIColor blackColor];
        editField.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;

        [self.contentView addSubview:editField];

        self.editField.enabled = NO;
        self.editField.hidden = YES;


        lineView = [[UIView alloc] initWithFrame:CGRectMake(80, 0, 1, self.contentView.bounds.size.height)];
        self.lineView.backgroundColor = [UIColor lightGrayColor];
        [self.contentView addSubview:lineView];
        self.lineView.hidden = YES;
    }
    return self;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {

    [super setSelected:selected animated:animated];

    // Configure the view for the selected state.
}

-(void)layoutSubviews
{
    [super layoutSubviews]; // layouts the cell as UITableViewCellStyleValue2 would normally look like

    editRect = CGRectMake(83, 12, self.contentView.frame.size.width-self.detailTextLabel.frame.origin.x-10, 19);
    editField.frame = editRect;
}


- (void)willTransitionToState:(UITableViewCellStateMask)state {
    [super willTransitionToState:state];

    if (state & UITableViewCellStateEditingMask) {
        self.detailTextLabel.hidden = YES;
        self.editField.enabled = YES;
        self.lineView.hidden = NO;
        self.editField.hidden = NO;
    }
}

- (void)didTransitionToState:(UITableViewCellStateMask)state {
    [super didTransitionToState:state];

    if (!(state & UITableViewCellStateEditingMask)) {
        self.editField.enabled = NO;
        self.editField.hidden = YES;
        self.lineView.hidden = YES;
        self.detailTextLabel.hidden = NO;
        self.editField.text = self.detailTextLabel.text;
    }
}


- (void)dealloc {
    [editField release];
    [lineView release];

    [super dealloc];
}


@end
Run Code Online (Sandbox Code Playgroud)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    // handling every section by hand since this view is essentially static. Sections 0, 1, 2, and 4 use a generic editable cell.
    // Section 3 uses the multiline address cell.

    static NSString *CellIdentifier = @"Cell";

    EditableCellStyle2 *cell = (EditableCellStyle2 *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (indexPath.section == 0 || indexPath.section == 1 || indexPath.section == 2 || indexPath.section == 4) {
        if (cell == nil) {
            cell = [[[EditableCellStyle2 alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier] autorelease];
        }
    }

    // Configure the Odometer
    if (indexPath.section == 0) {
        NSArray *array = [sectionsArray objectAtIndex:indexPath.section];
        NSDictionary *dictionary = [array objectAtIndex:indexPath.row];

        cell.textLabel.text = @"Odometer";
        cell.detailTextLabel.text = [NSString stringWithFormat:@"%@", [dictionary objectForKey:@"Odometer"]];
        cell.tag = kOdometer;
        cell.editField.text = cell.detailTextLabel.text;
        cell.editField.placeholder = @"Odometer";
        cell.editField.tag = kOdometer;
        cell.editField.keyboardType = UIKeyboardTypeNumberPad;

        // Create a view for the green checkmark for odometer input validation and set it as the right view.
        UIImage *checkImage = [UIImage imageNamed:@"tick.png"];
        UIImageView *checkImageView = [[[UIImageView alloc] initWithImage:checkImage] autorelease];
        cell.editField.rightView = checkImageView;
        cell.editField.rightViewMode = UITextFieldViewModeAlways;
    }

return cell;
}
Run Code Online (Sandbox Code Playgroud)

还有更多,但所有的细胞都以同样的方式建造.

问题是,在编辑模式下,垂直线将正确显示.当我离开编辑模式时,当我进入正常模式时屏幕外的任何单元格仍然具有垂直线(它不会被隐藏).此外,现在我已经为checkmark指示器添加了imageView,切换模式时屏幕外的任何单元都会获得复选标记.(只有第0部分设置).

我还注意到,如果我执行cell.setNeedsDisplay,如果数据源已更新,文本标签和详细文本标签将不会更新.我必须做[self.tableView reloadData]跳过任何活动的动画.

我确定这些问题与我使用自定义单元格+ dequeueReusableCellWithIdentifier有关,但我找不到具体的内容.

任何反馈或推动正确的方向将不胜感激.

编辑:不使用可重用的单元格似乎已经解决了上述问题.我仍然愿意接受有关单元代码的反馈.我忘记了另一个可能或可能没有关系的问题.我的一个单元格有一个"点击查看列表"按钮.如果我在编辑模式下将数据输入单元格,然后点击该按钮从列表中选择一些信息(它显示模态表视图),当我关闭模态视图时,所有单元格的编辑数据都已恢复为原始状态.当我解雇模态视图控制器时,我没有调用重载数据.我认为这可以通过不使用可重复使用的细胞来解决,但事实并非如此.

Mor*_*ast 8

您需要准备单元格以便重复使用.尝试将此添加到EditableCellStyle2实现中:

- (void)prepareForReuse {
    [super prepareForReuse];
    [self didTransitionToState:UITableViewCellStateDefaultMask];
}
Run Code Online (Sandbox Code Playgroud)


Ano*_*mie 5

也许你为你的帖子修剪了太多,但在发布的代码中,你的可重复使用的单元格处理都是错误的.

首先,每种不同类型的细胞都需要自己的细胞CellIdentifier.在您的情况下(从您的代码注释判断),这意味着第3部分与第0,1,2和4部分至少有不同的标识符.您可能还想为第0部分执行单独的标识符,因此您不需要必须继续删除和读取该复选标记.不同的标识符需要用于dequeueReusableCellWithIdentifier:和initWithStyle:reuseIdentifier:`用于适当的部分.

第二个问题是您没有正确重置单元格.必须对UITableViewCell执行两种"初始化":初始化对于其类型的每个单元都是相同的,初始化取决于显示的特定行.当分配新的小区时,第一种可以(并且应该)只进行一次.第二种必须每次都完成tableView:cellForRowAtIndexPath:.您似乎在其init方法中正确地为您的EditableTableCell2类做了第一次,但我在那里看不到您在哪里进行每行初始化:您永远不会重置selected,或者单元状态,或编辑字段的内容,或者删除checkImageView,因为第0部分与其他部分使用相同类型的单元格.如果需要,selected可以在prepareForReuseEditableTableCell2类上完成复位,状态和清除复选框图像和字段内容.

第三个问题,几乎可以肯定是由于过度修剪,你永远不会为第3部分创建这个"多行地址"单元格.你最终可能会重用一个随机的EditableTableCell2,或者可能会崩溃来自框架的异常你从零回来tableView:cellForRowAtIndexPath:.