1

我正在使用以下UIImages视频创建generateCGImagesAsynchronouslyForTimes

fileprivate func createImageFramesFromVideo(completion: @escaping ([UIImage]) -> Void) {
    guard let url = self.videoUrl else {
        return
    }
    
    let asset = AVAsset(url: url)
    let imageGenerator = AVAssetImageGenerator(asset: asset)
    let videoDuration = asset.duration
    
    //getting image snapshots more or less in half the video
    let time1 = CMTime(value: videoDuration.value/2 - videoDuration.value/10, timescale: videoDuration.timescale)
    let time2 = CMTime(value: videoDuration.value/2 - videoDuration.value/11, timescale: videoDuration.timescale)
    let time3 = CMTime(value: videoDuration.value/2 - videoDuration.value/12, timescale: videoDuration.timescale)
    let time4 = CMTime(value: videoDuration.value/2, timescale: videoDuration.timescale)
    let time5 = CMTime(value: videoDuration.value/2 + videoDuration.value/12, timescale: videoDuration.timescale)
    let time6 = CMTime(value: videoDuration.value/2 + videoDuration.value/11, timescale: videoDuration.timescale)
    let time7 = CMTime(value: videoDuration.value/2 + videoDuration.value/10, timescale: videoDuration.timescale)
    
    var imageArray : [UIImage] = []
    
    imageGenerator.generateCGImagesAsynchronously(forTimes: [NSValue(time: time1), NSValue(time: time2), NSValue(time: time3), NSValue(time: time4), NSValue(time: time5), NSValue(time: time6), NSValue(time: time7)]) { (time, image, time1, result, err) in
        if let err = err {
            print("there's an error in retrieving the images", err)
        }
       
        let theImage = UIImage(cgImage: image!)
        
        imageArray.append(theImage)
        
        if(result == .succeeded){
            completion(imageArray)
        }
    }
}

由于每次创建新图像时都会调用该函数的完成处理程序,因此completion()会多次调用该函数的完成处理程序。

我想实现completion()仅在创建所有图像(在本例中为 7)之后才调用它。我该怎么做?

4

1 回答 1

2

您需要使用 aDispatchGroup来等待几个异步函数完成。您需要确保对DispatchGroup.enter()和的调用leave()是平衡的(被调用的次数相同),因为当您使用 时dispatchGroup.notify(queue:),闭包只会被执行leave()一次enter()

您需要为数组enter的每个元素调用times(其中将包含 的CMTime变量time1time7然后在 的完成块中generateCGImagesAsynchronously(forTimes:,您调用leave()。这确保只有在为所有图像调用其自己的完成notify(queue:)时才会执行其闭包。generateCGImagesAsynchronously

fileprivate func createImageFramesFromVideo(completion: @escaping ([UIImage]) -> Void) {
    guard let url = self.videoUrl else { return }

    let asset = AVAsset(url: url)
    let imageGenerator = AVAssetImageGenerator(asset: asset)
    let videoDuration = asset.duration

    //getting image snapshots more or less in half the video
    let time1 = CMTime(value: videoDuration.value/2 - videoDuration.value/10, timescale: videoDuration.timescale)
    let time2 = CMTime(value: videoDuration.value/2 - videoDuration.value/11, timescale: videoDuration.timescale)
    let time3 = CMTime(value: videoDuration.value/2 - videoDuration.value/12, timescale: videoDuration.timescale)
    let time4 = CMTime(value: videoDuration.value/2, timescale: videoDuration.timescale)
    let time5 = CMTime(value: videoDuration.value/2 + videoDuration.value/12, timescale: videoDuration.timescale)
    let time6 = CMTime(value: videoDuration.value/2 + videoDuration.value/11, timescale: videoDuration.timescale)
    let time7 = CMTime(value: videoDuration.value/2 + videoDuration.value/10, timescale: videoDuration.timescale)
    let times = [NSValue(time: time1), NSValue(time: time2), NSValue(time: time3), NSValue(time: time4), NSValue(time: time5), NSValue(time: time6), NSValue(time: time7)]

    var imageArray : [UIImage] = []

    let dispatchGroup = DispatchGroup()
    times.forEach { _ in
        dispatchGroup.enter()
    }


    imageGenerator.generateCGImagesAsynchronously(forTimes: times) { (time, image, time1, result, err) in
        if let err = err {
            print("there's an error in retrieving the images", err)
        }

        let theImage = UIImage(cgImage: image!)

        imageArray.append(theImage)
        dispatchGroup.leave()
    }

    dispatchGroup.notify(queue: .main) {
        completion(imageArray)
    }
}
于 2020-09-30T09:51:36.440 回答