我有一个 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];
有帮助吗?

解决方案

插入、删除和移动节和项 从"Ios的集合视图编程指南":

要插入、删除或移动单个部分或项目,您必须遵循 这些步骤:

  1. 更新数据源对象中的数据。
  2. 调用集合视图的适当方法以插入或删除节或项。

在通知 任何更改的集合视图。集合视图方法假定 您的数据源包含当前正确的数据。如果是的话 不是,集合视图可能会收到错误的项目集 您的数据源或要求不存在的项目并使您的 应用程序。

因此,在您的情况下,您必须先将图像添加到集合视图数据源,然后调用 insertItemsAtIndexPaths.然后,集合视图将询问数据源委托函数以提供插入项的视图。

其他提示

我刚刚用Swift实现了这一点。所以我想分享我的实现。首先初始化一个NSBlockOperations数组:

    var blockOperations: [NSBlockOperation] = []

在控制器将改变,重新初始化数组:

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

在did change对象方法中:

    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!])
                }
            })
        )
    }
}

在did更改部分方法中:

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