加载 AVPlayer 时出现错误线程 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

Getting error Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT) when loading AVPlayer

当我 select 一个 collectionViewCell 时,我试图加载一个 AVPlayer,这是我在 didSelectItem 中的代码:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    if let item = items?[indexPath.item] {
        showPlayer(item: item)
    }
}

func showPlayer(item: Item) {

    let playerLauncher = PlayerLauncher()
    playerLauncher.showVideoPlayer()

    let playerView = PlayerView()
    playerView.item = item
    playerView.setupPlayerView()
}

这是我的 PlayerLauncher 文件:

class PlayerView: UIView {

    var item: Item? {
        didSet {
            if let id = item?.itemId {
               itemId = id
            } 
        }
    }

    var itemId = String()

    override init(frame: CGRect) {
        super.init(frame: frame)

        backgroundColor = UIColor(white: 0.3, alpha: 1)
    }

    var player: AVPlayer?

    func setupPlayerView() {

        let baseurl = "http://xample.com/play.m3u?id="

        let urlString = "\(baseurl)\(itemId)"
        print(urlString)
        if let url = URL(string: urlString) {
            player = AVPlayer(url: url)

            let playerLayer = AVPlayerLayer(player: player)
            self.layer.addSublayer(playerLayer)
            playerLayer.frame = self.frame

            let audioSession = AVAudioSession.sharedInstance()
            do{
                try audioSession.setCategory(AVAudioSessionCategoryPlayback)
            } catch let err {
                print(err)
                return
            }

            player?.play()

            player?.addObserver(self, forKeyPath: "currentItem.status", options: .new, context: nil)
        }
    }
}

class PlayerLauncher: NSObject {

    func showVideoPlayer() {
        print("Showing the player...")

        if let keyWindow = UIApplication.shared.keyWindow {
            let view = UIView(frame: keyWindow.frame)
            view.backgroundColor = UIColor.white

            view.frame = CGRect(x: keyWindow.frame.width - 10, y: keyWindow.frame.height - 10, width: 10, height: 10)

            let playerFrame = CGRect(x: 0, y: 0, width: keyWindow.frame.width, height: keyWindow.frame.height)
            let playerView = PlayerView(frame: playerFrame)
            view.addSubview(playerView)

            keyWindow.addSubview(view)

            UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
                view.frame = keyWindow.frame
            }, completion: { (completedAnimation) in
                //later...

            })
        }
    }
}

所以每当我 select 项目时,播放器开始加载,控制台打印 URL (因为我在那里添加了打印语句),这是它打印的内容:

http://xample.com/play.m3u?id=12345
(lldb)

然后它崩溃并在 AppDelegate 中显示 Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT) 错误。我该如何解决?

谢谢。

更新:

我稍微更改了 didSelectItem 函数。这是代码:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    if let item = items?[indexPath.item] {
        showPlayer(item: item)
    }
}

func showPlayer(item: Item) {
    let playerLauncher = PlayerLauncher()
    playerLauncher.showPlayer(item: item)
}

我将 PlayerView 中的 init 方法更改为:

var item: Item? {
    didSet {
        if let id = item?.itemId {
            itemId = id
        }
    }
}

init(frame: CGRect, item: Item) {
    super.init(frame: frame)
    self.item = item

    setupPlayerView()
    setupContainerView()
    backgroundColor = UIColor(white: 0.3, alpha: 1)
}

以及 PlayerLauncher 中所需的更改:

let playerView = PlayerView(frame: playerFrame, item: item)
view.addSubview(playerView)

我在 let playerView 行打断,我可以看到那里传递的项目 ID。但它没有传递给 PlayerView class 中的 urlString。因此,ID 仍然是 " ".

出现

class PlayerLauncher: NSObject

无法参考

let playerView = PlayerView()

尝试在函数范围之外定义它们,以便它们可以被函数更改并在函数外部引用。

我制作了一份指南,希望能说明您一直以来的误解。

我为没有使用 MARKDOWN 文本格式向其他读者道歉,但请将此视为我对原始 poster 的最大尝试。我们已经在之前的 post.

中进行了充分的讨论

那么,你如何解决这个问题? 估计没啥好直接给你代码的,请大家根据这个信息修改一下代码。

如果您有更多问题,我会尽力帮助您:)