Проголосовал за Догберта :-)

спрашиваю о точном коде, но об общей идее.

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

1) я пробовал использоватьOperation а такжеOperationQueue с представлением коллекции, какая предварительная выборка включена. Это быстро загружает viewController, но при прокрутке отбрасывает кадры.

2) Прямо сейчас я использую вид прокрутки иGCD но он загружает viewController слишком долго (потому что он применяет все фильтры сразу ко всем кнопкам внутри него), но затем он плавно прокручивается.

НОТА: Чтобы ответить на этот вопрос, нет необходимости читать приведенную ниже часть (я полагаю), однако, если вам интересно, как я пытаюсь реализовать функциональность, вы можете прочитать ее.

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

struct Filters {
var image: UIImage
var allFilters: [CIFilter] = []

init(image: UIImage) {

    self.image = image

    guard  let sepia = Sepia(image: image) else {return}

    allFilters.append(contentsOf: [sepia, sepia, sepia, sepia, sepia, sepia, sepia, sepia, sepia, sepia, sepia, sepia, sepia])

       }
  }

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

class Sepia: CIFilter {

var inputImage: CIImage?
var inputIntensity: NSNumber?

@objc override var filterName: String? {
    return NSLocalizedString("Sepia", comment: "Name of a Filter")
}

convenience init?(image: UIImage, inputIntensity: NSNumber? = nil) {
    self.init()

    guard let cgImage = image.cgImage else {
        return nil
    }

    if inputIntensity != nil {
        self.inputIntensity = inputIntensity
    } else {
        self.setDefaults()
    }

    let inputImage = CIImage(cgImage: cgImage)
    self.inputImage = inputImage
}

override func setDefaults() {
    inputIntensity = 1.0
}

override var outputImage: CIImage? {
    guard let inputImage = inputImage, let inputIntensity = inputIntensity else {
        return nil
    }

    let filter = CIFilter(name: "CISepiaTone", withInputParameters: [kCIInputImageKey: inputImage, kCIInputIntensityKey: inputIntensity])

   return filter?.outputImage

  }
}

В представлении контроллераviewDidLoad Я начинаюFilters структура:

self.filters = Filters(image: image)

Затем я вызываю метод, который настраивает некоторые представления (filterViews) на основе количества фильтров вfilters.allFilters массив и перебирает их и вызывает метод, который принимает миниатюруUIImage и применяет фильтр к нему, а затем возвращает его в обработчике завершения (я используюDispatchGroup в нем по причинам отладки). Вот метод, который применяет фильтр к миниатюре:

func imageWithFilter(filter: CIFilter, completion: @escaping(UIImage?)->Void) {

    let group = DispatchGroup()
    group.enter()
    DispatchQueue.global().async {
        guard let outputImage = filter.value(forKey: kCIOutputImageKey) as? CIImage, let cgImageResult = self.context.createCGImage(outputImage, from: outputImage.extent) else  {
            DispatchQueue.main.async {
                 completion(nil)
            }
            group.leave()
            return
        }

        let filteredImage = UIImage(cgImage: cgImageResult)
        DispatchQueue.main.async {
            print (filteredImage)
            completion(filteredImage)

        }

       group.leave()
    }

    group.notify(queue: .main) {
        print ("Filteres are set")
    }
}

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

Я пытался использоватьTime Profiler но это дает мне странные результаты. Например, он показывает, что выполнение в корне обратного следования занимает довольно много времени:

Когда я пытаюсь увидеть код в Xcode, я получаю следующее, что мало помогает:

Итак, это проблема. Если у вас есть какие-либо идеи о том, как это реализовано в приложении «Фотографии», что оно настолько быстрое и отзывчивое, или если у вас есть предложения о моей реализации, я был бы очень признателен за вашу помощь.

Ответы на вопрос(1)

Ваш ответ на вопрос