Ios 滚动UICollectionView时冻结

Ios 滚动UICollectionView时冻结,ios,swift,cifilter,ciimage,glkview,Ios,Swift,Cifilter,Ciimage,Glkview,我正在开发照片编辑器应用程序,但在UICollectionView中渲染过滤图像时遇到问题。我正在使用操作和操作队列。当我开始滚动collectionView时,过滤后的图像正在更新。我怎样才能修好它 图像过滤: class ImageFiltration: Operation { private let image: CIImage private let filterName: String! var imageWithFilter: CIImage? init(image: CIIma

我正在开发照片编辑器应用程序,但在UICollectionView中渲染过滤图像时遇到问题。我正在使用
操作
操作队列
。当我开始滚动collectionView时,过滤后的图像正在更新。我怎样才能修好它

图像过滤:

class ImageFiltration: Operation {
private let image: CIImage
private let filterName: String!

var imageWithFilter: CIImage?

init(image: CIImage, filterName: String) {
    self.image = image
    self.filterName = filterName
}

override func main() {
    if self.isCancelled {
        return
    }

    if let name = filterName {
        let filter = CIFilter(name: name, withInputParameters: [kCIInputImageKey: image])
        imageWithFilter = filter?.outputImage!
    }
} }

class PendingOperation {
lazy var filtrationInProgress = [IndexPath: Operation]()
lazy var filtrationQueue: OperationQueue = {
    var queue = OperationQueue()
    queue.name = "Filtration Operation"
    return queue
}() }
UIScrollViewDelegate:

extension PhotoEditorViewController: UIScrollViewDelegate {
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
    presenter.suspendAllOperations()
}

func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    if !decelerate {
        presenter.loadImagesForOnScreenCells(collectionView: filtersToolsView.collectionView) { (indexPath) in
            self.filtersToolsView.collectionView.reloadItems(at: [indexPath])
        }
        presenter.resumeAllOperations()
    }
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    presenter.loadImagesForOnScreenCells(collectionView: filtersToolsView.collectionView) { (indexPath) in
        self.filtersToolsView.collectionView.reloadItems(at: [indexPath])
    }
    presenter.resumeAllOperations()
} }
UICollectionView数据源:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell: PhotoEditorFilterCollectionViewCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)

    cell.layer.shouldRasterize = true
    cell.layer.rasterizationScale = UIScreen.main.scale
    cell.filteredImage.contentMode = .scaleAspectFill

    presenter.startFiltration(indexPath: indexPath) { (image, filterName) in
        cell.filteredImage.inputImage = image
        cell.filterNameLabel.text = filterName
    }

    return cell
}
实施启动过滤方法:

func startFiltration(indexPath: IndexPath, completion: @escaping (CIImage?, String) -> ()) {
    if let _ = pendingOperations.filtrationInProgress[indexPath] {
        return
    }

    let filteredImage = ImageFiltration(image: model.image,
                                        filterName: model.image.filters[indexPath.row].filterName)

    filteredImage.completionBlock = {
        if filteredImage.isCancelled {
            return
        }

        DispatchQueue.main.async {
            self.pendingOperations.filtrationInProgress.removeValue(forKey: indexPath)
            completion(filteredImage.imageWithFilter, self.model.image.filters[indexPath.row].filterDisplayName)
        }
    }

    pendingOperations.filtrationInProgress[indexPath] = filteredImage
    pendingOperations.filtrationQueue.addOperation(filteredImage)
}
操作方法:

func suspendAllOperations() {
    pendingOperations.filtrationQueue.isSuspended = true
}

func resumeAllOperations() {
    pendingOperations.filtrationQueue.isSuspended = false
}

func loadImagesForOnScreenCells(collectionView: UICollectionView,
                                completion: @escaping (IndexPath) -> ()) {
    let pathsArray = collectionView.indexPathsForVisibleItems

    let allPendingOperations = Set(Array(pendingOperations.filtrationInProgress.keys))
    let visiblePaths = Set(pathsArray as [IndexPath])
    var toBeCancelled = allPendingOperations

    toBeCancelled.subtract(visiblePaths)

    var toBeStarted = visiblePaths

    toBeStarted.subtract(allPendingOperations)

    for indexPath in toBeCancelled {
        if let pendingFiltration = pendingOperations.filtrationInProgress[indexPath] {
            pendingFiltration.cancel()
        }

        pendingOperations.filtrationInProgress.removeValue(forKey: indexPath)
    }

    for indexPath in toBeStarted {
        let indexPath = indexPath as IndexPath
        completion(indexPath)
    }
}
我正在用GLKView渲染一张图片


在scrollViewDidScroll上取消所有请求。最后滚动获取可见单元格并启动操作队列。这样,它将只使用您可见的单元内存,UI将不会卡住。
请参阅本教程,它与您的要求相同-

您好。您需要记住,任何用户启动的操作在运行时都将被赋予最高优先级,因此当滚动“收藏”视图时,您的图像处理代码将暂停。我认为您需要在后台通过回调进行图像处理,以在视图完成后更新视图。如果您需要有关如何编写代码的帮助,请让我知道。与您的问题无关,但将filterName设置为枚举可防止无效名称我稍微更改了我的代码,但现在并不是所有图像都在滚动时显示。