У меня есть базовое представление прокрутки 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>) { }
}
Спасибо @workingdogsupportUkraine, я использовал принудительное развертывание, чтобы упростить этот вопрос. Предположим, что проблема не в государстве.
поскольку AVPlayer является объектом, его следует инициализировать внутри makeUIViewController, что происходит только один раз, а не в иерархии представлений, которая инициализируется много раз.





Попробуйте этот подход, используя 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()
}
}
}
Отлично работает, спасибо. Не могли бы вы посмотреть: stackoverflow.com/questions/78447347/…
Обратите внимание: в вашем
@State var urlV: URLне должно бытьMessageView, используйтеlet urlV: URLи, конечно же, не используйте принудительное разворачивание!чего-либо, например URL-адреса. Точно так же не используйте@State var viewID: Stringв своемMessageVideoPlayerX.