繁体   English   中英

从另一个视图将变量传递给 SwiftUI AVPlayer

[英]Pass variable to SwiftUI AVPlayer from another view

这里的相对新手使用 SwiftUI 构建 iOS 应用程序。 试图寻找解决方案,但没有运气。

From my app home screen ("HomeView.swift"), when users select a thumbnail image of the video they want to play, the video's absolute URL on the web (which is retrieved from a local.json file) gets passed in the variable ("videoLink") 到视频播放器视图 ("VideoPlayer.swift")。

现在,如果简单地显示为文本,Xcode 可以让我成功渲染 videoLink 变量的值,如下所示:

Text("\(videoLink)")

它允许硬编码的 URL 与 AVPlayer 一起使用,如下所示:

let player = AVPlayer(url: URL(string: "http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8")!)

但是,当我尝试按以下方式将变量值与 AVPlayer 一起使用时,Xcode 会出错:

let player = AVPlayer(url: URL(string: "\(videoLink)")!)

这是错误消息:

“不能在属性初始化程序中使用实例成员 'videoLink';属性初始化程序在 'self' 可用之前运行。”

我在这里包含了 VideoPlayer.swift 视图的完整代码。

import SwiftUI
import AVKit

struct PlayerView: View {
    
    @ObservedObject var model = VideoModel()
    
    var videoLink = ""

    let player = AVPlayer(url: URL(string: "http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8")!)

    var body: some View {

        VideoPlayer(player: player) {
            VStack {
                Text("\(videoLink)")
                    .foregroundColor(.white)
                Spacer()
            }
        }
            .onAppear() {
                player.play()
            }
            .onDisappear() {
                player.pause()
            }
    }
}

任何提示将非常感谢!

有几种方法可以解决这个问题。

一种方法是让你的player变量成为可选的@State变量,并在onAppear设置它的值:

struct PlayerView: View {
    
    @ObservedObject var model = VideoModel()
    
    var videoLink : String
    
    @State private var player : AVPlayer?
    
    var body: some View {
        
        VideoPlayer(player: player) {
            VStack {
                Text("\(videoLink)")
                    .foregroundColor(.white)
                Spacer()
            }
        }
        .onAppear() {
            guard let url = URL(string: videoLink) else {
                return
            }
            player = AVPlayer(url: url)
            player?.play()
        }
        .onDisappear() {
            player?.pause()
        }
    }
}

另一种选择(我不太喜欢)是将播放器作为参数传递:

struct PlayerView: View {
    
    @ObservedObject var model = VideoModel()
    
    var videoLink : String
    var player : AVPlayer
    
    var body: some View {
        
        VideoPlayer(player: player) {
            VStack {
                Text("\(videoLink)")
                    .foregroundColor(.white)
                Spacer()
            }
        }
        .onAppear() {
            player.play()
        }
        .onDisappear() {
            player.pause()
        }
    }
}

并称之为:

PlayerView(videoLink: "url", player: AVPlayer(url: url))

我更喜欢第一种方法的一个原因是,在第二个选项中,如果父视图被重新渲染,它也会重新实例化AVPlayer ,而在第一个选项中,繁重的工作在onAppear中完成,然后保持在使用@State变量的渲染之间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM