SwiftUI技术问题:如何将ContentView的selectedIndex传递给LoopingPlayerUIView类
问题分析与解决方案
你之前创建myView = ContentView()的方式完全无效,因为这个myView是全新的ContentView实例,和界面上正在显示的ContentView没有任何关联,它的selectedIndex永远是初始值0,自然无法响应真实的Tab切换操作。
下面是正确的实现方案:
步骤1:重构LoopingPlayerUIView,暴露播放控制接口
先把播放器改成实例属性,方便外部控制,同时添加专门的方法来根据selectedIndex更新播放状态:
import UIKit import AVKit class LoopingPlayerUIView: UIView { private let playerLayer = AVPlayerLayer() private var playerLooper: AVPlayerLooper? private var player: AVQueuePlayer? // 改为实例属性,方便外部访问 override init(frame: CGRect) { super.init(frame: frame) setupPlayerResources() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } // 初始化播放器资源 private func setupPlayerResources() { let storage = Storage.storage() let storageRef = storage.reference().child("User1/pexels-christopher-schultz-5147455-1080x1920-30fps (1).mp4") storageRef.downloadURL { [weak self] url, error in guard let self = self else { return } // 确定视频URL let targetURL: URL if let error = error { print(error) targetURL = URL(string: "https://i.imgur.com/U52l05s.mp4")! } else { guard let validURL = url else { return } targetURL = validURL } // 创建播放器项目 let asset = AVAsset(url: targetURL) let item: AVPlayerItem = error != nil ? CachingPlayerItem(asset: asset) : AVPlayerItem(asset: asset) // 初始化播放器 self.player = AVQueuePlayer() self.playerLayer.player = self.player self.playerLayer.videoGravity = .resizeAspectFill self.layer.addSublayer(self.playerLayer) // 设置循环播放 self.playerLooper = AVPlayerLooper(player: self.player!, templateItem: item) } } // 外部调用:根据selectedIndex控制播放/暂停 func updatePlayState(selectedIndex: Int) { guard let player = player else { return } if selectedIndex == 0 { player.play() } else { player.pause() print("pause") } } override func layoutSubviews() { super.layoutSubviews() playerLayer.frame = bounds } }
步骤2:创建SwiftUI与UIKit的桥接器
通过UIViewRepresentable把UIKit的LoopingPlayerUIView包装成SwiftUI可用的视图,同时绑定selectedIndex:
struct LoopingPlayerView: UIViewRepresentable { @Binding var selectedIndex: Int func makeUIView(context: Context) -> LoopingPlayerUIView { let playerView = LoopingPlayerUIView() // 设置初始播放状态 playerView.updatePlayState(selectedIndex: selectedIndex) return playerView } // 当selectedIndex变化时自动触发,更新播放状态 func updateUIView(_ uiView: LoopingPlayerUIView, context: Context) { uiView.updatePlayState(selectedIndex: selectedIndex) } }
步骤3:在ContentView中使用包装后的视图
直接把绑定的selectedIndex传递给播放器视图,Tab切换时自动同步状态:
struct ContentView: View { @State private var selectedIndex: Int = 0 var body: some View { TabView(selection: $selectedIndex) { // 第一个Tab:视频播放器 LoopingPlayerView(selectedIndex: $selectedIndex) .tabItem { Image(systemName: "play.rectangle") Text("视频") } .tag(0) // 其他Tab示例 Text("第二个页面") .tabItem { Image(systemName: "square") Text("页面2") } .tag(1) } } }
内容的提问来源于stack exchange,提问作者user22030043
相关产品推荐
相关产品推荐

