Пользовательские проблемы перерисовки UITableViewCell - PullRequest
9 голосов
/ 18 февраля 2011

У меня есть пользовательская ячейка 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

#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

- (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;
}

Это еще не все, но все ячейки построены одинаково.

Проблема заключается в том, что в режиме редактирования вертикальнаялинии будут отображаться правильно.Когда я выхожу из режима редактирования, все ячейки, которые были вне экрана, когда я перехожу в нормальный режим, все еще имеют вертикальную линию (она не скрывается).Кроме того, теперь, когда я добавил imageView для индикатора флажка, все ячейки, которые находятся за пределами экрана при переключении режимов, получают флажок.(только раздел 0 устанавливает его).

Я также заметил, что если я сделаю cell.setNeedsDisplay, текстовая метка и метка подробного текста не будут обновляться, если источник данных был обновлен.Я должен сделать [self.tableView reloadData], который пропускает любые активные анимации.

Я уверен, что эти проблемы связаны со мной, используя пользовательскую ячейку + dequeueReusableCellWithIdentifier, но я не могу точно найти, что.

Любая обратная связь или толчок в правильном направлении приветствуются.

Редактировать: Неиспользуемые ячейки, по-видимому, решили вышеуказанные проблемы.Я все еще открыт для отзывов о коде сотовой связи.Я забыл еще одну проблему, которая может или не может быть связана.В одной из моих ячеек есть кнопка «Просмотреть список».Если я ввожу данные в ячейки в режиме редактирования, затем нажимаю на эту кнопку, чтобы выбрать некоторую информацию из списка (она отображает модальное представление таблицы), когда я отклоняю модальное представление, все отредактированные данные ячеек возвращаются кисходное состояние.Я не вызываю данные перезагрузки, когда увольняю модальный контроллер представления.Я думал, что это можно исправить, не используя повторно используемые ячейки, но это не так.

Ответы [ 2 ]

8 голосов
/ 23 июня 2011

Вам необходимо подготовить ячейку для повторного использования.Попробуйте добавить это к реализации EditableCellStyle2:

- (void)prepareForReuse {
    [super prepareForReuse];
    [self didTransitionToState:UITableViewCellStateDefaultMask];
}
5 голосов
/ 23 июня 2011

Возможно, вы слишком много урезали для своего поста, но в опубликованном коде ваша многоразовая обработка ячеек неверна.

Прежде всего, каждый тип ячейки нуждается в своем CellIdentifier. В вашем случае (судя по вашему комментарию к коду) это означает, что как минимум другой идентификатор для раздела 3 отличается от разделов 0, 1, 2 и 4. Возможно, вы также захотите сделать отдельный идентификатор для раздела 0, так что вы не будете должны продолжать снимать и читать эту галочку. Различный идентификатор необходимо использовать как для dequeueReusableCellWithIdentifier:, так и для initWithStyle: reuseIdentifier: `для соответствующих разделов.

Вторая проблема заключается в том, что вы неправильно сбрасываете ячейки. Существует два «вида» инициализации, которые должны быть выполнены для UITableViewCell: инициализация, которая одинакова для каждой ячейки ее типа, и инициализация, которая зависит от конкретной отображаемой строки. Первый вид может (и должен) выполняться только один раз, когда выделяется новая ячейка. Второй вид нужно делать каждый раз через tableView:cellForRowAtIndexPath:. Похоже, вы правильно делаете первый для вашего класса EditableTableCell2 в его методе init, но я не вижу там, где вы выполняете инициализацию для каждой строки: вы никогда не сбрасываете selected, ни состояние ячейки, ни содержимое редактирования. поле или удалите checkImageView, так как вы используете ячейку такого же типа для раздела 0 по сравнению с другими разделами. Если вы хотите, сброс selected, состояние и очистка изображения флажка и содержимого поля можно выполнить в prepareForReuse в вашем классе EditableTableCell2.

Третья проблема, которая почти наверняка связана с чрезмерным усечением, заключается в том, что вы никогда не создадите эту ячейку с «многострочным адресом» для раздела 3. В конечном итоге вы, возможно, повторно используете случайный EditableTableCell2 или, возможно, произойдет сбой исключения рамки при возврате ноль из tableView:cellForRowAtIndexPath:.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...