Dispatch Group的奇怪行为

时间:2016-12-05 18:35:50

标签: ios avfoundation grand-central-dispatch

我从iOS App遇到了非常奇怪的崩溃。下面的函数是一些协议的实现,所以我不能改变它的声明来使用一些成功/失败回调。它有输入参数,并在输出端需要AVAsset。我的问题是在写资产期间我在离开调度组(dg变量)时遇到了奇怪的崩溃。我用评论标记了崩溃线。这种崩溃并不总是发生。只是不时。这是功能:

func writeAsset(to url: URL, metadataArray: [AVTimedMetadataGroup]) -> AVAsset {
        let writer = try! AVAssetWriter(url: url, fileType: AVFileTypeQuickTimeMovie)
        writer.movieTimeScale = track.timeScale

        // setup writer, inputs and metadata adaptor and so on ...

        if writer.startWriting() {
            writer.startSession(atSourceTime: kCMTimeZero)
        }

        let writeQueue = DispatchQueue(label: "HH.Write.Track.Queue")

        let dg = DispatchGroup()
        var i = 0

        dg.enter() // Entering to the group
        writerMetadataIn.requestMediaDataWhenReady(on: writeQueue) {
            while writerMetadataIn.isReadyForMoreMediaData {
                //let group = ..fetch next group to write
                if i < metadataArray.count {
                    let group = metadataArray[i]
                    if writerMetadataAdaptor.append(group) {
                    }
                    i += 1
                } else {
                    writerMetadataIn.markAsFinished()
                    writer.finishWriting {
                        dg.leave() // CRASH IN THIS LINE
                    }
                    break
                }
            }
        }
        dg.wait()

        let writtenAsset = AVAsset(url: url)
        return writtenAsset
    }

有人知道这次崩溃的原因是什么?我只有xCode中的崩溃报告中的这些信息。

2 个答案:

答案 0 :(得分:2)

我怀疑你的问题是因为你进入调度组一次,然后(有时)在循环内不止一次,你没有平衡调用。即。你打电话的时间比你打电话的时间多。

答案 1 :(得分:0)

找到问题的解决方案。它与DispatchGroup无关,但与AVAssetWriter和AVTimedMetadataGroup元素的输入数组有关。每个元素都有时间范围。如果其中两个的开始时间相同,则在附加此组期间写入将处于错误状态,并且行为非常不可预测。我不知道为什么在离开小组期间错误出现在这一行中,但对我来说解决方案是检测具有相同开始时间的组并跳过它们。