【问题标题】:Freezing the interface at the time of playerQueue creation (Swift 5)在创建 playerQueue 时冻结界面(Swift 5)
【发布时间】:2020-10-22 08:05:19
【问题描述】:

我正在创建一个音乐播放器。它从设备内存(从 Documents 文件夹)播放曲目。 我遇到了一个问题,当有很多曲目(200 或更多)时,在加载曲目列表时,我的界面会冻结。我找了很长时间的问题根源,尝试了不同的选项,我找到了——这就是我创建 playerQueue 的函数createPlayerQueue
我想了解:这真的从设备中占用了这么多资源还是我的代码不是很好?我该如何解决这个问题?

func createPlayerQueue(from content: [URL]) -> [AVPlayerItem] {
        var playerQueue: [AVPlayerItem] = []
        let items = content.map { AVURLAsset(url: $0) }.map { AVPlayerItem(asset: $0) } //at this point the interface freezes
        playerQueue = items
        return playerQueue
    }

我使用函数结果来创建我的模型:

private var playerQueue: [AVPlayerItem] = []

func setupTrackModels(content: [URL]) -> [TrackModelProtocol] {
        playerQueue = audioPlayer.createPlayerQueue(from: content)
        var tracks: [TrackModelProtocol] = []
        
        for index in 0..<playerQueue.count {
            
            var artwork: UIImage?
            
            let playerItem = playerQueue[index]
            let metadataList = playerItem.asset.metadata
            
            for item in metadataList {
                guard let key = item.commonKey?.rawValue, let value = item.value else {
                    continue
                }
                
                switch key {
                case "artwork" where value is Data:
                    artwork = UIImage(data: value as! Data)
                default:
                    continue
                }
            }
            
            let track = TrackFromDeviceMemory(
                fileName: content[index].lastPathComponent,
                duration: playerQueue[index].asset.duration.seconds,
                artwork: artwork,
                url: content[index].absoluteURL)
            
            tracks.append(track)
        }
        
        return tracks
    }

我在viewWillAppear 函数中调用了这个函数,这样每次返回这个视图时我都能得到实际的文件列表。

【问题讨论】:

    标签: ios swift grand-central-dispatch avplayer


    【解决方案1】:

    几天前偶然发现了一个类似的问题,并发现AVPlayerItem 实例化是资源繁重的,因此将其分派到自定义队列是个好主意。 This page 详细介绍了该主题。

    另外,有点挑剔 - 你可以将你的 createPlayerQueue 方法缩短到这个,不需要将 items 分配给 playerQueue,并且由于只有一行代码,即使 return 也可以省略:

    func createPlayerQueue(from content: [URL]) -> [AVPlayerItem] {
        content.map { AVURLAsset(url: $0) }.map { AVPlayerItem(asset: $0) }
    }
    

    【讨论】:

    • 非常感谢!我一定会读到这一页。关于“返回”的一个小说明:在其他情况下我可以跳过它吗?这是 Swift 5 的一些新功能吗?
    猜你喜欢
    • 1970-01-01
    • 2013-04-05
    • 1970-01-01
    • 2015-02-08
    • 2014-05-05
    • 1970-01-01
    • 2016-07-22
    • 2017-10-21
    • 1970-01-01
    相关资源
    最近更新 更多