swift - Swift:无法将类型“()->()”的值转换为闭包结果类型“Void”
问题描述
这是所有的代码。有一个按钮按下动作函数调用prepareVideo。
@IBAction func nextButtonPressed(_ sender: Any) {
if MyVariables.isScreenshot == true {
prepareScreenshot {
self.moveOn()
}
} else {
prepareVideo()
}
}
func prepareVideo(){
let outputFileName = NSUUID().uuidString
let outputFilePath = (NSTemporaryDirectory() as NSString).appendingPathComponent((outputFileName as NSString).appendingPathExtension("mov")!)
self.videoURL = URL(fileURLWithPath: outputFilePath)
trimVideo(sourceURL: self.footageURL!, destinationURL: self.videoURL!, trimPoints: [(trimmerView.startTime!,trimmerView.endTime!)], completion: prepareVideoThumbnail {
self.moveOn
}) //Xcode mentions error here
}
func trimVideo (sourceURL: URL, destinationURL: URL, trimPoints: TrimPoints, completion: @escaping () -> ()) {
guard sourceURL.isFileURL else { return }
guard destinationURL.isFileURL else { return }
let options = [
AVURLAssetPreferPreciseDurationAndTimingKey: true
]
let asset = AVURLAsset(url: sourceURL, options: options)
let preferredPreset = AVAssetExportPresetPassthrough
if verifyPresetForAsset(preset: preferredPreset, asset: asset) {
let composition = AVMutableComposition()
let videoCompTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: CMPersistentTrackID())
let audioCompTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: CMPersistentTrackID())
guard let assetVideoTrack: AVAssetTrack = asset.tracks(withMediaType: .video).first else { return }
guard let assetAudioTrack: AVAssetTrack = asset.tracks(withMediaType: .audio).first else { return }
var accumulatedTime = kCMTimeZero
for (startTimeForCurrentSlice, endTimeForCurrentSlice) in trimPoints {
let durationOfCurrentSlice = CMTimeSubtract(endTimeForCurrentSlice, startTimeForCurrentSlice)
let timeRangeForCurrentSlice = CMTimeRangeMake(startTimeForCurrentSlice, durationOfCurrentSlice)
do {
try videoCompTrack!.insertTimeRange(timeRangeForCurrentSlice, of: assetVideoTrack, at: accumulatedTime)
try audioCompTrack!.insertTimeRange(timeRangeForCurrentSlice, of: assetAudioTrack, at: accumulatedTime)
accumulatedTime = CMTimeAdd(accumulatedTime, durationOfCurrentSlice)
}
catch let compError {
print("TrimVideo: error during composition: \(compError)")
}
}
guard let exportSession = AVAssetExportSession(asset: composition, presetName: preferredPreset) else { return }
exportSession.outputURL = destinationURL as URL
exportSession.outputFileType = AVFileType.m4v
exportSession.shouldOptimizeForNetworkUse = true
removeFileAtURLIfExists(url: destinationURL as URL)
exportSession.exportAsynchronously {
completion()
}
}
else {
print("TrimVideo - Could not find a suitable export preset for the input video")
}
}
func prepareVideoThumbnail(completion: @escaping () -> Void) {
guard let VideoURL = self.videoURL else { return }
self.thumbnailImage = setThumbnailFrom(path: VideoURL)
completion()
//moveOn()
//DispatchQueue.main.async {
// self.performSegue(withIdentifier: "CreatePost_Segue", sender: nil)
//}
}
func moveOn(){
guard self.thumbnailImage != nil else {
return
}
if MyVariables.isScreenshot == true {
guard self.screenshotOut != nil else {
return
}
self.performSegue(withIdentifier: "CreatePost_Segue", sender: nil)
} else {
guard self.thumbnailImage != nil else {
return
}
self.performSegue(withIdentifier: "CreatePost_Segue", sender: nil)
//now I set those three varibles?
}
}
PrepareVideo 不接受回调/完成处理程序,但它调用了 trimVideo,它确实接受了完成处理程序。在此我调用prepareVideoThumbnail,它应该调用它的完成处理程序{self.moveOn}。PrepareVideoThumbnail 应该是 trimVideo 怀疑的 () -> () 类型。所以我不确定为什么它抱怨关闭结果类型“无效”。我意识到 self.moveOn() 会导致这种情况,但我没有调用它,请注意我使用的 self.moveOn 没有括号。我该如何解决?
解决方案
的语法:
trimVideo(sourceURL: self.footageURL!, destinationURL: self.videoURL!, trimPoints: [(trimmerView.startTime!,trimmerView.endTime!)], completion: prepareVideoThumbnail {
self.moveOn
})
应该:
trimVideo(sourceURL: self.footageURL!, destinationURL: self.videoURL!, trimPoints: [(trimmerView.startTime!,trimmerView.endTime!)]) {
self.prepareVideoThumbnail() {
self.moveOn()
}
}
顺便说一句 - 为不执行任何异步处理的函数(如您的preparreVideoThumbnail
函数)设置完成参数是没有意义的。
然后你的代码变成:
trimVideo(sourceURL: self.footageURL!, destinationURL: self.videoURL!, trimPoints: [(trimmerView.startTime!,trimmerView.endTime!)]) {
self.prepareVideoThumbnail()
self.moveOn()
}
并消除prepareVideoThumbnail
函数上的完成参数。
推荐阅读
- elasticsearch - 带有规范化器的 ElasticSearch 关键字文件不适用于通配符查询
- python-3.x - 我应该如何在 Python 中使用 id() 函数?
- python-3.x - 使用 boto3 在 dynamodb 中返回所有具有最大排序键的哈希键项
- r - 我想在 for 循环中的 ggplot2 中绘制多个 geom_line,所以我能够绘制线条但面临着色问题。任何人都可以建议如何做
- git - 如何找出一个合并提交中包含哪些提交?
- java - 如何通过 Eclipse 将自动化测试用例关联到 Azure
- mysql - 如何使用 node.js 将 excel 文件导入 MySQL?
- ruby-on-rails - 按轨道 4 上的条件排序
- node.js - 如何在 MongoDB 上高效查询复杂的层次结构
- php - php imagemagick 或任何其他方式来查找拼图的 xy 坐标