ScrollView 视频渲染不流畅

问题描述 投票:0回答:1

我有一个基本的 SwiftUI 滚动视图,其中包含许多视频。当我取出视频播放器内的红色时,滚动视图非常平滑,我可以尽可能快地向下和向上滑动,而不会出现任何故障。但是,当我添加红色并向下滑动然后向上滑动时,滚动视图会在视频再次渲染时出现故障。我该如何修复这个故障?此外,Instagram 或 Twitter 等应用程序的视频在出现时就已渲染,滚动离开并返回不会导致它们重新渲染。我怎样才能实现这样的行为?这样做可能会修复视频渲染时的故障。

复制可粘贴代码

import SwiftUI
import AVFoundation
import AVKit

struct allVids: Identifiable, Hashable {
    var id: String
    var video: String?
}

struct MainTabViewXX: View {
    @State var someData: [allVids] = [
                allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com:443/v0/b/hustle-85b6c.appspot.com/o/stories%2F0FCE66A1-06F7-47CC-A38A-9A95192A2728.mp4?alt=media&token=57921e5a-e5e6-4b54-919b-39be9fbead84"),
                allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com:443/v0/b/hustle-85b6c.appspot.com/o/stories%2F0FCE66A1-06F7-47CC-A38A-9A95192A2728.mp4?alt=media&token=57921e5a-e5e6-4b54-919b-39be9fbead84"),
                allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com:443/v0/b/hustle-85b6c.appspot.com/o/stories%2F0FCE66A1-06F7-47CC-A38A-9A95192A2728.mp4?alt=media&token=57921e5a-e5e6-4b54-919b-39be9fbead84"),
                allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com:443/v0/b/hustle-85b6c.appspot.com/o/stories%2F0FCE66A1-06F7-47CC-A38A-9A95192A2728.mp4?alt=media&token=57921e5a-e5e6-4b54-919b-39be9fbead84"),
                allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com:443/v0/b/hustle-85b6c.appspot.com/o/stories%2F0FCE66A1-06F7-47CC-A38A-9A95192A2728.mp4?alt=media&token=57921e5a-e5e6-4b54-919b-39be9fbead84"),
                allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com:443/v0/b/hustle-85b6c.appspot.com/o/stories%2F0A514500-F1A0-4093-98A2-2847FE46484A.mp4?alt=media&token=69afd165-1ab6-4686-9ad2-2ce485090fe1"),
                allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com:443/v0/b/hustle-85b6c.appspot.com/o/stories%2FE8937043-873E-4178-A90D-C6C03684C700.mp4?alt=media&token=ddc1f616-5427-4722-a96f-ab81739b243e"),
                allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com:443/v0/b/hustle-85b6c.appspot.com/o/stories%2FE8937043-873E-4178-A90D-C6C03684C700.mp4?alt=media&token=ddc1f616-5427-4722-a96f-ab81739b243e"),
                allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com:443/v0/b/hustle-85b6c.appspot.com/o/stories%2FE8937043-873E-4178-A90D-C6C03684C700.mp4?alt=media&token=ddc1f616-5427-4722-a96f-ab81739b243e"),
                allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com:443/v0/b/hustle-85b6c.appspot.com/o/stories%2FE8937043-873E-4178-A90D-C6C03684C700.mp4?alt=media&token=ddc1f616-5427-4722-a96f-ab81739b243e"),
                allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com:443/v0/b/hustle-85b6c.appspot.com/o/stories%2F0FCE66A1-06F7-47CC-A38A-9A95192A2728.mp4?alt=media&token=57921e5a-e5e6-4b54-919b-39be9fbead84")]
    
    var body: some View {
        ScrollView {
           LazyVStack(spacing: 1){
               ForEach(someData) { message in
                    MessageView(urlV: URL(string: message.video ?? "")!, video: message)
               }
           }
        }.ignoresSafeArea()
    }
}

struct MessageView: View {
    @State var urlV: URL
    let video: allVids
    
    var body: some View {
        VStack {
            MessageVideoPlayerX(url: urlV, viewID: video.id)
        }
    }
}

struct MessageVideoPlayerX: View {
    @State var player: AVPlayer? = nil
    let url: URL
    @State var viewID: String
    
    init(url: URL, viewID: String? = nil) {
        self.url = url
        _viewID = State(initialValue: viewID ?? UUID().uuidString)
    }
    
    var body: some View {
        VStack {
            if let vid = player {
                VidPlayer(player: vid).frame(width: 200, height: 350)
            }
            Color.red.frame(width: 200, height: 300)
        }
        .onAppear {
            if player == nil {
                player = AVPlayer(url: url)
            }
            self.player?.isMuted = true
            
            self.player?.play()
        }
        .onDisappear {
            self.player?.pause()
        }
    }
}

struct VidPlayerX : UIViewControllerRepresentable {
    var player : AVPlayer
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<VidPlayerX>) -> AVPlayerViewController {

        let controller = AVPlayerViewController()
        controller.player = player
        controller.showsPlaybackControls = false
        controller.allowsVideoFrameAnalysis = false
        controller.videoGravity = .resizeAspectFill
        return controller
    }
    
    func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext<VidPlayerX>) { }
}
swift swiftui avfoundation
1个回答
0
投票

尝试这种方法,使用

let player: AVPlayer
而不是在
.onAppear
每次出现
MessageVideoPlayerX
时。

struct MessageVideoPlayerX: View {
    let player: AVPlayer // <--- here
    let url: URL
    let viewID: String

   init(url: URL, viewID: String? = nil) {
       self.url = url
       self.viewID = viewID ?? UUID().uuidString
       self.player = AVPlayer(url: url)  // <--- here
   }

    var body: some View {
        VStack {
            VidPlayerX(player: player).frame(width: 200, height: 350) // <--- here
            Color.red.frame(width: 200, height: 350)
        }
       .onAppear {
           player.isMuted = true
           player.play()
       }
       .onDisappear {
           player.pause()
       }
   }
}
© www.soinside.com 2019 - 2024. All rights reserved.