簡體   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