Реконструкция UITableView с базовыми данными [дубликат]

Можно также хотеть смотреть на OAuth, появляющийся открытый протокол для основанной на маркере авторизации, конкретно предназначающейся http пчела.

Это очень похоже на подход, проявленный , flickr и помнит молоко пчела "отдыха" (не обязательно хорошие примеры успокоительной пчелы, но хорошие примеры основанного на маркере подхода).

23
задан Community 23 May 2017 в 12:16
поделиться

5 ответов

Вот что теперь официально работает: удаление, перемещение и вставка. Я «подтверждаю» порядок каждый раз, когда на него влияет действие редактирования.

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section != kHeaderSection) {

        if (editingStyle == UITableViewCellEditingStyleDelete) {

            @try {
                LinkObj * link = [self.fetchedResultsController objectAtIndexPath:indexPath];

                debug_NSLog(@"Deleting at indexPath %@", [indexPath description]);
            //debug_NSLog(@"Deleting object %@", [link description]);

                if ([self numberOfBodyLinks] > 1) 
                    [self.managedObjectContext deleteObject:link];

            }
            @catch (NSException * e) {
                debug_NSLog(@"Failure in commitEditingStyle, name=%@ reason=%@", e.name, e.reason);
            }

        }
        else if (editingStyle == UITableViewCellEditingStyleInsert) {
            // we need this for when they click the "+" icon; just select the row
            [theTableView.delegate tableView:tableView didSelectRowAtIndexPath:indexPath];
        }
    }
}

- (BOOL)validateLinkOrders {        
    NSUInteger index = 0;
    @try {      
        NSArray * fetchedObjects = [self.fetchedResultsController fetchedObjects];

        if (fetchedObjects == nil)
            return NO;

        LinkObj * link = nil;       
        for (link in fetchedObjects) {
            if (link.section.intValue == kBodySection) {
                if (link.order.intValue != index) {
                    debug_NSLog(@"Info: Order out of sync, order=%@ expected=%d", link.order, index);

                    link.order = [NSNumber numberWithInt:index];
                }
                index++;
            }
        }
    }
    @catch (NSException * e) {
        debug_NSLog(@"Failure in validateLinkOrders, name=%@ reason=%@", e.name, e.reason);
    }
    return (index > 0 ? YES : NO);
}


- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
    NSArray * fetchedObjects = [self.fetchedResultsController fetchedObjects];  
    if (fetchedObjects == nil)
        return;

    NSUInteger fromRow = fromIndexPath.row + NUM_HEADER_SECTION_ROWS;
    NSUInteger toRow = toIndexPath.row + NUM_HEADER_SECTION_ROWS;

    NSInteger start = fromRow;
    NSInteger end = toRow;
    NSInteger i = 0;
    LinkObj *link = nil;

    if (toRow < start)
        start = toRow;
    if (fromRow > end)
        end = fromRow;

    @try {

        for (i = start; i <= end; i++) {
            link = [fetchedObjects objectAtIndex:i]; //
            //debug_NSLog(@"Before: %@", link);

            if (i == fromRow)   // it's our initial cell, just set it to our final destination
                link.order = [NSNumber numberWithInt:(toRow-NUM_HEADER_SECTION_ROWS)];
            else if (fromRow < toRow)
                link.order = [NSNumber numberWithInt:(i-1-NUM_HEADER_SECTION_ROWS)];        // it moved forward, shift back
            else // if (fromIndexPath.row > toIndexPath.row)
                link.order = [NSNumber numberWithInt:(i+1-NUM_HEADER_SECTION_ROWS)];        // it moved backward, shift forward
            //debug_NSLog(@"After: %@", link);
        }
    }
    @catch (NSException * e) {
        debug_NSLog(@"Failure in moveRowAtIndexPath, name=%@ reason=%@", e.name, e.reason);
    }
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {    
    @try {
        switch (type) {
            case NSFetchedResultsChangeInsert:
                [theTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
                [self validateLinkOrders];
                break;
            case NSFetchedResultsChangeUpdate:
                break;
            case NSFetchedResultsChangeMove:
                self.moving = YES;
                [self validateLinkOrders];
                break;
            case NSFetchedResultsChangeDelete:
                [theTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                [self validateLinkOrders];
                break;
            default:
                break;
        }
    }
    @catch (NSException * e) {
        debug_NSLog(@"Failure in didChangeObject, name=%@ reason=%@", e.name, e.reason);
    }
}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
    switch(type) {
        case NSFetchedResultsChangeInsert:
            [self.theTableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.theTableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    // The fetch controller has sent all current change notifications, so tell the table view to process all updates.
    @try {
        if (self.theTableView != nil) {
            //[self.theTableView endUpdates];
            if (self.moving) {
                self.moving = NO;
                [self.theTableView reloadData];
                //[self performSelector:@selector(reloadData) withObject:nil afterDelay:0.02];
            }
            [self performSelector:@selector(save) withObject:nil afterDelay:0.02];
        }   

    }
    @catch (NSException * e) {
        debug_NSLog(@"Failure in controllerDidChangeContent, name=%@ reason=%@", e.name, e.reason);
    }
}
7
ответ дан 29 November 2019 в 02:39
поделиться

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

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

    for (i = start; i <= end; i++) {
            NSIndexPath *tempPath = [NSIndexPath indexPathForRow:i inSection:toIndexPath.section];
            LinkObj *link = [fetchedResultsController objectAtIndexPath:tempPath];
            //[managedObjectContext deleteObject:[fetchedResultsController objectAtIndexPath:tempPath]];
            link.order = [NSNumber numberWithInteger:i];
            [managedObjectContext refreshObject:link mergeChanges:YES];
            //[managedObjectContext insertObject:link];
    }

Загвоздка в том, что вы фактически не меняете порядок в базовой модели. Эти indexPaths взяты из UITableViewController, он сообщает вам, что пользователь перетаскивал их в нужные места, и вам необходимо обновить соответствующие данные. Но fetchedResultsController всегда находится в порядке сортировки, поэтому, пока вы не измените эти свойства, ничего не перемещалось.

Дело в том, что они не были перемещены, вас вызывают, чтобы сказать вам, что вам нужно их переместить (путем настройки сортируемое свойство). Вам действительно нужно что-то вроде:

NSNumber *targetOrder = [fetchedResultsController objectAtIndexPath:toIndexPath];
LinkObj *link = [fetchedResultsController objectAtIndexPath:FromPath];
link.order = targetOrder;

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

вас вызывают, чтобы сказать вам, что вам нужно переместить их (путем настройки свойства sortable). Вам действительно нужно что-то вроде:

NSNumber *targetOrder = [fetchedResultsController objectAtIndexPath:toIndexPath];
LinkObj *link = [fetchedResultsController objectAtIndexPath:FromPath];
link.order = targetOrder;

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

вас вызывают, чтобы сказать вам, что вам нужно переместить их (путем настройки свойства sortable). Вам действительно нужно что-то вроде:

NSNumber *targetOrder = [fetchedResultsController objectAtIndexPath:toIndexPath];
LinkObj *link = [fetchedResultsController objectAtIndexPath:FromPath];
link.order = targetOrder;

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

8
ответ дан 29 November 2019 в 02:39
поделиться
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
    [self.pairs exchangeObjectAtIndex:sourceIndexPath.row withObjectAtIndex:destinationIndexPath.row];
    [self performSelector:@selector(reloadData) withObject:nil afterDelay:0.02];
}

- (void)reloadData{
    [table reloadData];
}

Стол не может перезагружаться во время движения, перезагрузите его после задержки, и все будет в порядке.

1
ответ дан 29 November 2019 в 02:39
поделиться

Извини, Грег, я уверен, что делаю что-то не так, но твой ответ не работает для меня.

Хотя все мои объекты проверяются правильно, когда я выхожу из режима редактирования, один из строки замирают (элементы управления редактированием не исчезают), а затем ячейки не реагируют должным образом.

Возможно, моя проблема в том, что я не знаю, как использовать заданное вами свойство перемещения (self.moving = YES ). Не могли бы вы прояснить это? Большое спасибо.

Хорхе

1
ответ дан 29 November 2019 в 02:39
поделиться

Это очень сложный способ реализации такой функциональности. Гораздо более простой и элегантный способ можно найти здесь: UITableView Core Data reordering

1
ответ дан 29 November 2019 в 02:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: