如何在 Swift 中关闭和完成处理程序后获取数据

Posted

技术标签:

【中文标题】如何在 Swift 中关闭和完成处理程序后获取数据【英文标题】:How to get data after after closure & completion handler in Swift 【发布时间】:2020-09-06 18:08:46 【问题描述】:

我是 Swift 的新手,我试图找到一个解决方案,但没有成功解决这个问题。

我在 ViewDidLoad() 中:

    AudioContext.load(fromAudioURL: self.url)  audioContext in

        guard let audioContext = audioContext else 
            fatalError("Couldn't create the audioContext")
        
        
        self.outputArray = self.render(audioContext: audioContext, targetSamples: 300)
        samples = self.outputArray.map  -Int($0) 
        print("TOTAL1:\(samples)") **// IT WORKS OK**
        
    
    print("TOTAL2:\(samples)") // IT DOES NOT WORK => Give nothing

以及带有完成处理程序的函数:

public static func load(fromAudioURL audioURL: URL, completionHandler: @escaping (_ audioContext: AudioContext?) -> ())  
    let asset = AVURLAsset(url: audioURL, options: [AVURLAssetPreferPreciseDurationAndTimingKey: NSNumber(value: true as Bool)])
    
    guard let assetTrack = asset.tracks(withMediaType: AVMediaType.audio).first else 
        fatalError("Couldn't load AVAssetTrack")
    
    
    asset.loadValuesAsynchronously(forKeys: ["duration"]) 
        var error: NSError?
        let status = asset.statusOfValue(forKey: "duration", error: &error)
        switch status 
        case .loaded:
            guard
                let formatDescriptions = assetTrack.formatDescriptions as? [CMAudioFormatDescription],
                let audioFormatDesc = formatDescriptions.first,
                let asbd = CMAudioFormatDescriptionGetStreamBasicDescription(audioFormatDesc)
                else  break 
            
            let totalSamples = Int((asbd.pointee.mSampleRate) * Float64(asset.duration.value) / Float64(asset.duration.timescale))
            let audioContext = AudioContext(audioURL: audioURL, totalSamples: totalSamples, asset: asset, assetTrack: assetTrack)
        
            completionHandler(audioContext)
            
            
            return 
            
        case .failed, .cancelled, .loading, .unknown:
            print("Couldn't load asset: \(error?.localizedDescription ?? "Unknown error")")

        @unknown default:
            print("Couldn't load asset: \(error?.localizedDescription ?? "Unknown error")")

        
      
        
        completionHandler(nil)
    

我应该怎么做才能确保打印 TOTAL2 的结果与 TOTAL1 相同。事实上,我需要在闭包之外使用数组 SAmple,但我不明白该怎么做。

如果您能帮助我,非常感谢 :-) 干杯

【问题讨论】:

在调用闭包之前你不能对数据做任何事情,但是如果不知道你将如何使用它,很难说什么解决方案适合你。 this question有一些建议 非常感谢乔金。多亏了你,我才能解决这个问题,我还发现了一个有用的链接:appcoda.com/swift-delegate 【参考方案1】:

这个转义闭包将在未来某个时间执行,而不是绝对在print("TOTAL2:\(samples)") 之后执行。解决方案之一是将样本保存为视图属性并将其存储在您正在打印print("TOTAL1:\(samples)") 的闭包中。然后你可以稍后使用它。但问题是如何知道是否调用了闭包以及samples 是否有最新数据。

或者更好的是,您可以从第一个闭包中调用需要samples 的函数。确保使用weak self

【讨论】:

以上是关于如何在 Swift 中关闭和完成处理程序后获取数据的主要内容,如果未能解决你的问题,请参考以下文章

当我在谷歌设置android中关闭和打开位置时,FusedLocation 不起作用

如何在 iOS + Swift 中关闭我的应用程序的 Internet 访问

iOS 应用程序在 swift 中关闭视图后冻结

chapter_21字节流字符流

解析查询后 Swift 数组为空 - 完成处理程序?

斯威夫特,如何让完成处理程序按我的意愿工作?