В свободное время я занимаюсь разработкой приложения для редактирования видео для iOS.
Я только что возобновил работу над ним после нескольких недель посещения других проектов, и, хотя я не сделал ни одного значительные изменения в коде - , теперь он падает каждый раз, когда я пытаюсь экспортировать мою композицию видео .
Я извлек и собрал точно такой же коммит, который был успешно загружен в TestFlight тогда (и он работал на нескольких устройствах без сбоев), так что, возможно, это проблема с последним Xcode / iOS SDK что я обновил с тех пор?
Код падает на _xpc_api_misuse в потоке:
com.apple.coremedia.basicvideocompositor.output
Навигатор отладки:
Во время создания cra sh в навигаторе отладки было более 70 потоков, поэтому возможно, что-то не так, и приложение использует слишком много потоков (никогда их не видел).
Мое приложение накладывает «водяной знак» на экспортируемое видео, используя текстовый слой. После игры я обнаружил, что cra sh можно предотвратить, если я закомментирую код водяного знака:
guard let exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality) else {
return failure(ProjectError.failedToCreateExportSession)
}
guard let documents = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) else {
return failure(ProjectError.temporaryOutputDirectoryNotFound)
}
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd_HHmmss"
let fileName = dateFormatter.string(from: Date())
let fileExtension = "mov"
let fileURL = documents.appendingPathComponent(fileName).appendingPathExtension(fileExtension)
exporter.outputURL = fileURL
exporter.outputFileType = AVFileType.mov
exporter.shouldOptimizeForNetworkUse = true // check if needed
// OFFENDING BLOCK (commenting out averts crash)
if addWaterMark {
let frame = CGRect(origin: .zero, size: videoComposition.renderSize)
let watermark = WatermarkLayer(frame: frame)
let parentLayer = CALayer()
let videoLayer = CALayer()
parentLayer.frame = frame
videoLayer.frame = frame
parentLayer.addSublayer(videoLayer)
parentLayer.addSublayer(watermark)
videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer)
}
// END OF OFFENDING BLOCK
exporter.videoComposition = videoComposition
exporter.exportAsynchronously {
// etc.
Код слоя водяного знака:
class WatermarkLayer: CATextLayer {
private let defaultFontSize: CGFloat = 48
private let rightMargin: CGFloat = 10
private let bottomMargin: CGFloat = 10
init(frame: CGRect) {
super.init()
guard let appName = Bundle.main.infoDictionary?["CFBundleName"] as? String else {
fatalError("!!!")
}
self.foregroundColor = CGColor.srgb(r: 255, g: 255, b: 255, a: 0.5)
self.backgroundColor = CGColor.clear
self.string = String(format: String.watermarkFormat, appName)
self.font = CTFontCreateWithName(String.watermarkFontName as CFString, defaultFontSize, nil)
self.fontSize = defaultFontSize
self.shadowOpacity = 0.75
self.alignmentMode = .right
self.frame = frame
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented. Use init(frame:) instead.")
}
override func draw(in ctx: CGContext) {
let height = self.bounds.size.height
let fontSize = self.fontSize
let yDiff = (height-fontSize) - fontSize/10 - bottomMargin // Bottom (minus margin)
ctx.saveGState()
ctx.translateBy(x: -rightMargin, y: yDiff)
super.draw(in: ctx)
ctx.restoreGState()
}
}
Есть идеи, что может произойти?
Возможно, мой код делает что-то не так, что каким-то образом "получил пропуск" в предыдущем SDK из-за какой-то ошибки Apple, которая была исправлена, или из-за дыры в реализации 'что подключено?