UITableViewCell показывает два разных элемента, пока я перемещаю его в режиме редактирования - PullRequest
2 голосов
/ 29 мая 2011

У меня есть базовое приложение для iPhone «Список дел», подкрепленное Core Data.У меня проблемы с реализацией системы, которая позволяет пользователю выбирать порядок сортировки (Альфа, Дата создания, Пользовательская).Если они выбирают пользовательские, они могут перемещать элементы вручную в режиме редактирования.

В настоящий момент отображение таблицы и основные данные правильно отражают выбор сортировки.Однако, если я делаю что-то вроде следующего, я получаю странную ситуацию, как показано на скриншоте ниже.

Причины Проблема:

  1. Запустите приложение и измените сортировку - скажем, с даты, измененной наАльфа
  2. Изменить на пользовательскую сортировку
  3. Попробуйте переместить элемент в режиме редактирования (ошибка появляется только при удерживании и перетаскивании элемента)

Снимок экрана:

Image of problem

Когда изменяется предпочтение сортировки, я по сути убиваю свой NSManagedResultsFetcher, создаю новый с новым дескриптором сортировки и перезагружаю таблицу

- (void)startFetcher
{
    BOOL                            success;
    NSError *                       error;
    NSFetchRequest *                fetchRequest;
    NSSortDescriptor *              sortDescriptor;
    OurListsAppDelegate*    delegate;

    delegate = [[UIApplication sharedApplication] delegate]; 

    assert([ListMaster sharedListMaster] != nil);
    assert([ListMaster sharedListMaster].managedObjectContext != nil);

    NSPredicate *predicate = [NSPredicate predicateWithFormat:
                              @"(parentCreatedUdid = %@) AND (parentCreatedDate = %@)", self.parentCreatedUdid, self.parentCreatedDate];

    if (self.parentItem != nil)
    {
        sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:self.parentItem.sortPreference ascending:YES] autorelease];
    }
    else
    {
       sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:delegate.rootSortPreference ascending:YES] autorelease];
    }

    assert(sortDescriptor != nil);

    fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
    assert(fetchRequest != nil);

    [fetchRequest setPredicate:predicate];

    [fetchRequest setEntity:[ListMaster sharedListMaster].listEntity];
    [fetchRequest setFetchBatchSize:20];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];

    assert(self.fetcher == nil);
    self.fetcher = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[ListMaster sharedListMaster].managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    assert(self.fetcher != nil);

    self.fetcher.delegate = self;

    success = [self.fetcher performFetch:&error];
    if ( ! success ) {
        [[QLog log] logWithFormat:@"viewer fetch failed %@", error];
    }
}

Иметод, вызываемый при изменении порядка сортировки

- (void)restartFetcher
{
    [_fetcher release];
    self.fetcher = nil;
    [self startFetcher];
    [self reloadTable];
}

Редактировать: добавленный ниже код для каждого запроса

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

    UITableViewCell *   result;

    assert(tv == self.tableView);
    assert(indexPath != NULL);

    if ( [self hasNoItems] )
    {

        // There are no items to display; return a cell that simple says "No items".

        result = [self.tableView dequeueReusableCellWithIdentifier:@"cell"];
        if (result == nil) {
            result = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"] autorelease];
            assert(result != nil);

            result.textLabel.text = @"No items";
            result.textLabel.textColor = [UIColor darkGrayColor];
            result.textLabel.textAlignment = UITextAlignmentCenter;
        }
        result.selectionStyle = UITableViewCellSelectionStyleNone;
    } 
    else
    {
        ListItem *         item;


        item = [self.fetcher objectAtIndexPath:indexPath];
        assert([item isKindOfClass:[ListItem class]]);

        UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:@"cell"];

        if (cell == nil)
        {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"] autorelease];
            assert(cell != nil);

            assert(cell.selectionStyle == UITableViewCellSelectionStyleBlue);;
        }

        ToggleImageControl *toggleControl = [[ToggleImageControl alloc] initWithFrame: CGRectMake(4, 6, 32, 32) status:item.isDone];
        toggleControl.tag = indexPath.row;  
        [cell.contentView addSubview: toggleControl];

        [toggleControl release];

        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 0, 260, 44)];

        label.text = item.name;
        label.textAlignment = UITextAlignmentLeft;

        [cell.contentView addSubview:label];
        [label release];        


        if ([item.isList boolValue] == YES)
        {
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        }
        else
        {
            cell.accessoryType = UITableViewCellAccessoryNone;
        }

        result = cell;
    }

    return result;
}

1 Ответ

1 голос
/ 30 мая 2011

Ваша проблема в этих строках,

ToggleImageControl *toggleControl = [[ToggleImageControl alloc] initWithFrame: CGRectMake(4, 6, 32, 32) status:item.isDone];
toggleControl.tag = indexPath.row;  
[cell.contentView addSubview: toggleControl];

[toggleControl release];

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 0, 260, 44)];

label.text = item.name;
label.textAlignment = UITextAlignmentLeft;

[cell.contentView addSubview:label];
[label release]; 

Это проблема повторного использования ячейки.Многоразовые ячейки должны быть сброшены каждый раз перед их настройкой.В этом случае я понял, что это проблема, когда я заметил, что содержимое одной ячейки сливается с содержимым другой.Когда такое случается, обычно это проблема.Что вы делаете неправильно, так это то, что вы добавляете оба объекта, которые вы создали выше, каждый раз, когда ячейка используется повторно.В случае управления переключением они перекрываются, и вы не заметите, но текст меняется и перекрытие выделяется.

Что вы можете сделать?

Вы можете выполнить поискдля обоих объектов и удалите их из своей ячейки, а затем сделайте то, что вы делаете выше, или вы можете создать собственный подкласс UITableViewCell и добавить два retain ed свойства - одно для элемента управления переключателем и одно для меткипозже сделайте это,

ToggleImageControl *toggleControl = [[ToggleImageControl alloc] initWithFrame: CGRectMake(4, 6, 32, 32) status:item.isDone];
toggleControl.tag = indexPath.row;  
cell.toggleControl = toggleControl;

[toggleControl release];

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 0, 260, 44)];

label.text = item.name;
label.textAlignment = UITextAlignmentLeft;

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