Вопрос

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

Получив данные, я хотел бы сделать следующее:

[self.collectionView performBatchUpdates:^{
    for (UIImage *image in images) {
        [self.collectionView insertItemsAtIndexPaths:****]
    }
} completion:nil];

Теперь вместо ***, я должен передать массив NSIndexPaths, который должен указывать на расположение новых элементов, которые нужно вставить.Я очень запутался, поскольку после указания местоположения, как мне предоставить фактическое изображение, которое должно отображаться в этом месте?

Спасибо


ОБНОВЛЯТЬ:

resultsSize содержит размер массива источника данных, self.results, прежде чем новые данные будут добавлены из данных в newImages.

[self.collectionView performBatchUpdates:^{

    int resultsSize = [self.results count];
    [self.results addObjectsFromArray:newImages];
    NSMutableArray *arrayWithIndexPaths = [NSMutableArray array];

    for (int i = resultsSize; i < resultsSize + newImages.count; i++)
          [arrayWithIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];

          [self.collectionView insertItemsAtIndexPaths:arrayWithIndexPaths];

} completion:nil];
Это было полезно?

Решение

Видеть Вставка, удаление и перемещение разделов и элементов из "Руководство по программированию Collection View для iOS":

Чтобы вставить, удалить или перемещать один раздел или элемент, вы должны выполнить эти шаги:

  1. Обновите данные в объекте источника данных.
  2. Вызовите соответствующий метод представления коллекции, чтобы вставить или удалить раздел или элемент.

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

Итак, в вашем случае вы должны сначала добавить изображение в источник данных представления коллекции, а затем вызвать insertItemsAtIndexPaths.Затем представление коллекции запросит функцию делегата источника данных предоставить представление для вставленного элемента.

Другие советы

Я только что реализовал это с помощью Swift.Поэтому я хотел бы поделиться своей реализацией.Сначала инициализируйте массив NSBlockOperations:

    var blockOperations: [NSBlockOperation] = []

В контроллере изменится, повторно инициализируйте массив:

func controllerWillChangeContent(controller: NSFetchedResultsController) {
    blockOperations.removeAll(keepCapacity: false)
}

В методе объекта изменения:

    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {

    if type == NSFetchedResultsChangeType.Insert {
        println("Insert Object: \(newIndexPath)")

        blockOperations.append(
            NSBlockOperation(block: { [weak self] in
                if let this = self {
                    this.collectionView!.insertItemsAtIndexPaths([newIndexPath!])
                }
            })
        )
    }
    else if type == NSFetchedResultsChangeType.Update {
        println("Update Object: \(indexPath)")
        blockOperations.append(
            NSBlockOperation(block: { [weak self] in
                if let this = self {
                    this.collectionView!.reloadItemsAtIndexPaths([indexPath!])
                }
            })
        )
    }
    else if type == NSFetchedResultsChangeType.Move {
        println("Move Object: \(indexPath)")

        blockOperations.append(
            NSBlockOperation(block: { [weak self] in
                if let this = self {
                    this.collectionView!.moveItemAtIndexPath(indexPath!, toIndexPath: newIndexPath!)
                }
            })
        )
    }
    else if type == NSFetchedResultsChangeType.Delete {
        println("Delete Object: \(indexPath)")

        blockOperations.append(
            NSBlockOperation(block: { [weak self] in
                if let this = self {
                    this.collectionView!.deleteItemsAtIndexPaths([indexPath!])
                }
            })
        )
    }
}

В методе раздела изменений:

func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {

    if type == NSFetchedResultsChangeType.Insert {
        println("Insert Section: \(sectionIndex)")

        blockOperations.append(
            NSBlockOperation(block: { [weak self] in
                if let this = self {
                    this.collectionView!.insertSections(NSIndexSet(index: sectionIndex))
                }
            })
        )
    }
    else if type == NSFetchedResultsChangeType.Update {
        println("Update Section: \(sectionIndex)")
        blockOperations.append(
            NSBlockOperation(block: { [weak self] in
                if let this = self {
                    this.collectionView!.reloadSections(NSIndexSet(index: sectionIndex))
                }
            })
        )
    }
    else if type == NSFetchedResultsChangeType.Delete {
        println("Delete Section: \(sectionIndex)")

        blockOperations.append(
            NSBlockOperation(block: { [weak self] in
                if let this = self {
                    this.collectionView!.deleteSections(NSIndexSet(index: sectionIndex))
                }
            })
        )
    }
}

И, наконец, в контроллере Did был изменен метод содержимого:

func controllerDidChangeContent(controller: NSFetchedResultsController) {        
    collectionView!.performBatchUpdates({ () -> Void in
        for operation: NSBlockOperation in self.blockOperations {
            operation.start()
        }
    }, completion: { (finished) -> Void in
        self.blockOperations.removeAll(keepCapacity: false)
    })
}

Я лично также добавил некоторый код в метод deinit, чтобы отменить операции, когда ViewController вот-вот будет освобожден:

deinit {
    // Cancel all block operations when VC deallocates
    for operation: NSBlockOperation in blockOperations {
        operation.cancel()
    }

    blockOperations.removeAll(keepCapacity: false)
}

Я столкнулся с аналогичной проблемой при удалении элемента из индекса, и это то, что, я думаю, нам нужно делать при использовании performBatchUpdates: метод.

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

2# Удалить элемент из массива.

3# Обновите представление коллекции, перезагрузив данные.

[self.collectionView performBatchUpdates:^{
            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:sender.tag inSection:0];
            [self.collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
            [self.addNewDocumentArray removeObjectAtIndex:sender.tag];
        } completion:^(BOOL finished) {
            [self.collectionView reloadData];
        }];

Это поможет мне удалить все сбои и ошибки утверждения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top