Странная анимация при перемещении последней строки вне раздела и удалении раздела - PullRequest
2 голосов
/ 31 марта 2012

У меня есть многосекционный просмотр таблицы.В режиме редактирования я разрешаю перемещение строк из одного раздела в другой.После удаления последней строки из одного раздела я удаляю этот раздел.Поэтому я использую deleteSection внутри moveRowAtIndexPath.

Когда последний элемент перемещается из раздела, заголовок раздела исчезает, как и планировалось.Но есть очень странная ошибка анимации, когда перемещенная строка, кажется, «сливается» со строкой, над которой она была опущена, и пустая строка отображается в нижней части раздела «to» (возможно, потому что numberOfRows для этого разделаправильно, но 2 ряда находятся в одинаковом положении).Еще более странно, что когда я нажимаю на элемент управления переупорядочением для этой строки (не перемещая элемент, просто касаясь и отпуская), два элемента «исчезают».

Я разместил видео , демонстрирующее это.

Я попытался обернуть изменения в своих данных и просмотреть изменения в начале / конце обновлений, но безрезультатно.

Я загрузил тестовый проект здесь , и ятакже разместим код ниже.Пара моментов:

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

Код (все это в демонстрационном проекте):

Я настроил свои массивы в loadView:

- (void)loadView{
array1 = [NSMutableArray array];
[array1 addObject:@"test 0"];
[array1 addObject:@"test 1"];
[array1 addObject:@"test 2"];

    array2 = [NSMutableArray array];
    [array2 addObject:@"test a"];
    [array2 addObject:@"test b"];

    [super loadView];
}

У меня также есть метод, который возвращает комбинацию этих массивов - он используется в качестве источника данных:

- (NSMutableArray *)sourceArray{
NSMutableArray *result = [NSMutableArray array];
if (array1.count > 0) {
    [result addObject:array1];
}
if (array2.count >0) {
    [result addObject:array2];
    }
    return result;
}

, который учитывает очень простое количество строк / разделов:

   - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return self.sourceArray.count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return [[self.sourceArray objectAtIndex:section] count];
}

Стандартное форматирование ячейки / заголовка:

  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    cell.textLabel.text = [[self.sourceArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
    return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return [NSString stringWithFormat:@"Section %i", section];
}

Здесь я делаю магию

    // Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
    NSMutableArray *fromArray = [self.sourceArray objectAtIndex:fromIndexPath.section]; 
    NSMutableArray *toArray = [self.sourceArray objectAtIndex:toIndexPath.section];

    NSString *movedObject = [[self.sourceArray objectAtIndex:fromIndexPath.section] objectAtIndex:fromIndexPath.row];

    [fromArray removeObject:movedObject];
    [toArray insertObject:movedObject atIndex:toIndexPath.row];

        if ([self.tableView numberOfRowsInSection: fromIndexPath.section] == 0) {
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:fromIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
        }
    }

Ответы [ 7 ]

3 голосов
/ 05 апреля 2012

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

Я подозреваю, что когда этот метод источника данных вызывается табличным представлением, егоСостояние все еще находится в середине выполнения перемещения, поэтому вызов 'deleteSections' заставит таблицу попытаться удалить строку, которую вы перемещаете.Это не столько слияние, сколько тот факт, что оно исчезает с той же скоростью, что и заголовок раздела, а тот, что ниже, просто отступает, чтобы заполнить пространство.

Нажатие на элемент управления заставляет представление таблицы перестраивать саму себя и понимать, что строка на самом деле не пропала.

Чтобы попытаться обойти это, попробуйте запустить удаление в следующем цикле выполнения, используявызов диспетчеризации, например:

if ([self.tableView numberOfRowsInSection: fromIndexPath.section] == 0) {
    dispatch_async(dispatch_get_main_queue(), ^() {
        [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:fromIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
    });
}

. Это приведет к тому, что удаление все еще будет выполняться в главном потоке, но при этом будет разрешено выполнение 'moveRow' и любого стека вызовов, в котором он находится до завершения своей логики перед удалениемзвоните

2 голосов
/ 06 апреля 2012

Ваша проблема в анимации.Одно выполняется, а другое еще не завершено (перемещение и удаление анимации), в результате чего одна ячейка будет нарисована на другой.Вы можете убедиться в этом, переместив клетки снова.Правильный порядок будет отображаться.Согласно Apple docs для UITableView:

Примечание. Источник данных не должен вызывать setEditing: animated: изнутри своей реализации tableView: commitEditingStyle: forRowAtIndexPath :.Если по какой-либо причине это должно произойти, он должен вызвать его после задержки, используя executeSelector: withObject: afterDelay: метод.

Поэтому, чтобы исправить это, сделайте это с вашим кодом:

if ([self.tableView numberOfRowsInSection: fromIndexPath.section] == 0) {
   [self performSelector:@selector(someMethod:) withObject:fromIndexPath afterDelay:1.0];
}

- (void) someMethod:(NSIndexPath *) fromIndexPath {
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:fromIndexPath.section]  withRowAnimation:UITableViewRowAnimationFade];
}

Должно работать нормально.Просто измените задержку на что-то более короткое, что подходит вам.

0 голосов
/ 24 марта 2013

решение, которое потеряло анимацию в последнем ряду:

if([listOfItemsOnTransaction count]==indexPath.row){ 
  [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil]     
   withRowAnimation:UITableViewRowAnimationFade];
    [self.tableView reloadData];
   }else
   {
       [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] 
         withRowAnimation:UITableViewRowAnimationFade];


   }
0 голосов
/ 06 апреля 2012

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

Попробуйте заменить свой код следующим кодом.

-(void)deleteSection:(NSIndexSet*)indexSet
{
    [self.tableView deleteSections:indexSet withRowAnimation:UITableViewRowAnimationFade];
}

// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
    NSMutableArray *fromArray = [self.sourceArray objectAtIndex:fromIndexPath.section]; 
    NSMutableArray *toArray = [self.sourceArray objectAtIndex:toIndexPath.section];

    NSString *movedObject = [[self.sourceArray objectAtIndex:fromIndexPath.section] objectAtIndex:fromIndexPath.row];

    [fromArray removeObject:movedObject];
    [toArray insertObject:movedObject atIndex:toIndexPath.row];

    if ([self.tableView numberOfRowsInSection: fromIndexPath.section] == 0) {
        [self performSelector:@selector(deleteSection:) withObject:[NSIndexSet indexSetWithIndex:fromIndexPath.section] afterDelay:1.0];
//      [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:fromIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
    }
}
0 голосов
/ 02 апреля 2012

Поменяйте местами порядок fromArray и toArray в вашем коде.Если элемент имеет счет сохранения 1 до удаления его из массива, он будет иметь счет хранения 0 до добавления его в toArray.

Если вы поменяете порядок, элемент перейдет изсохраните счет от 1 до 2, а затем вернитесь к 1, когда удаление будет завершено.

0 голосов
/ 02 апреля 2012

Вы должны перезагрузить просмотр таблицы после удаления раздела.Попробуйте этот код.

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
    NSMutableArray *fromArray = [self.sourceArray objectAtIndex:fromIndexPath.section]; 
    NSMutableArray *toArray = [self.sourceArray objectAtIndex:toIndexPath.section];

    NSString *movedObject = [[self.sourceArray objectAtIndex:fromIndexPath.section] objectAtIndex:fromIndexPath.row];

    [fromArray removeObject:movedObject];
    [toArray insertObject:movedObject atIndex:toIndexPath.row];

        if ([self.tableView numberOfRowsInSection: fromIndexPath.section] == 0) {
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:fromIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
            [self.tableView reloadData];
        }

    }
0 голосов
/ 31 марта 2012

На случай, если ваши строки или то, что находится внутри них, может сфокусироваться, проверили ли вы, что вы назвали resignFirstResponder или [view endEditing:YES]? Мы увидели это, когда использовали текстовые поля и (IIRC также зависело от версии iOS 4) оставили фокус в одном из полей.

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