3

当特定单元格移动到超级视图时,我遇到了 UITableView 在滚动时滞后的问题。

我编写了自己的 IPFormKit,以便轻松创建具有不同类型 inputViews 的漂亮输入表单,而无需为每个表单字段/单元格手动重新编码所有内容。

我有一个 UITableViewController 来初始化我的 IPFormKit 及其字段。加载出列的- (UITableViewCell *) cellForRowAtIndexPath:(NSIndexPath)indexPath;自定义单元格(称为 IPFormTableViewCell)并将 IPFormField 分配给每个单元格。

自定义 UITableViewCell (IPFormTableViewCell) 在初始化时使用 CGRectZero 创建所有(可能)需要的输入视图(UITextField、UITextView、CustomUILabel)。

inputView根据 IPFormField 的类型(已作为单元格的 iVar 初始化)的匹配被调整大小并作为子视图添加到内部cell.contentView

- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath)indexPath

对于 UITextField 和 CustomUILabel 这可以完美地工作,但是当 inputView 是 UIText View时,当第一次显示这个单元格时,UITableView 的滚动滞后(稍微)明显。

当滚动一点后单元格将在稍后再次显示时(即使单元格被重用,因此 UITextView 被删除和读取),这些单元格没有延迟并且滚动非常流畅。

我已经没有想法了,这种滞后的原因可能是什么。任何想法都值得赞赏。

PS:延迟在 iPhone 4 和 iPhone 4S 上都很明显,并且持续时间几乎完全相同(因此它不应该与 CPU 相关)

UITableViewController.m

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"IPFormFieldCell";

    // Get Form Field for indexPath
    IPFormField *formField = [self.form fieldAtIndexPath:indexPath];

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

    if (cell == nil) {
        cell = [[[IPTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.backgroundView = nil;
        cell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"background.png"]];
        cell.selectedBackgroundView = nil;
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
    }

    [cell assignFormField:formField];

    return cell;
}  

IPFormTableViewCell.m

- (void)assignFormField:(IPFormField *)field:

- (void) assignFormField:(IPFormField *)field {
    if (formField != nil) {
        formField.inputView = nil; // unlink old field
    }

    self.formField = field;

    // Change Field Label
    [fieldLabel setText:[field label]];

    // Add an Input View to the Field
    UIView *labelView = nil;
    UIView *inputView = nil;

    switch (formField.type) {
        case IPFormFieldTypeTextField:
        {
            labelView = fieldLabel;

            UITextField *textField = inputTextField;
            textField.delegate = (IPFormTextField *)formField;
            textField.inputAccessoryView = [formField.form inputAccessoryView];
            textField.placeholder = [self.formField stringFromValue:self.formField.defaultValue];
            textField.keyboardType = [(IPFormTextField *)formField keyboardType];

            if (self.formField.value == nil || [[self.formField stringFromValue:self.formField.value] isEqualToString:[self.formField stringFromValue:self.formField.defaultValue]]) {
                textField.clearsOnBeginEditing = YES;
            } else {
                textField.text = [self.formField stringFromValue:self.formField.value];
                textField.clearsOnBeginEditing = NO;
            }

            inputView = textField;
            break;
        }

        case IPFormFieldTypeTextArea:
        {            
            UITextView *textView = inputTextView;
            textView.delegate = (IPFormTextArea *)formField;
            textView.inputAccessoryView = [formField.form inputAccessoryView];

            if (self.formField.value == nil || ![[self.formField stringFromValue:self.formField.value] length] > 0) {
                textView.text = [self.formField stringFromValue:self.formField.defaultValue];
            } else {
                textView.text = [self.formField stringFromValue:self.formField.value];
            }

            inputView = textView;
            break;
        }

        default:
            break;
    }

    self.leftItem = labelView;
    self.rightItem = inputView;

    if (leftItem != nil) {
        [self.contentView addSubview:leftItem];
    }

    if (rightItem != nil) {
        [self.contentView addSubview:rightItem];
    }

    formField.inputView = rightItem;
}
4

2 回答 2

1

显然,cellForRowAtIndexPath:我的 dataSource 使用了一个字段的属性,该属性设置为@property (nonatomic, copy)而不是@property (nonatomic, readonly).

现在我已经修复了它,滚动不再滞后。

于 2013-01-06T15:49:14.477 回答
0

正如我猜想的那样,您的问题在于您的自定义控件。是的,您正在重用该单元格,但这并没有在您的情况下提供任何内容,因为每次您请求该单元格时,您都在为每个单元格创建新的自定义控件。我的建议是,您可以创建自定义控件并将其保留为实例变量,并在需要时返回它们而无需很多if-elses,或者,您可以为两种情况创建自定义单元格,并使用不同的单元格标识符将它们出列并重用它们。祝你好运!

于 2013-01-05T10:33:57.207 回答