Im building a video feed that scrolls and acts similar to TikTok or equivalent. Running into an issue where the video doesnt stop playing after you scroll to the next video, but stops only after the video after that. so it takes 2 scrolls for the video to stop playing, meanwhile every video starts playing when its in view normally, but because it takes 2 scrolls for the first video to stop, there are always 2 videos playing at the same time.
Is there a function i can add so that only one video plays at a time? I tried the activeIndex with the onappear / on disappear but that didnt change anything other than all the videos following the first video wouldnt play.
Here is some of the code I have, I need some dire help here.
Swift Pros only - thank you in advance!
import AVKit
import MapKit
struct LiveEventCard: View {
let event: CustomEvent
var isActive: Bool // Determines if the video should play
let onCommentButtonTapped: () -> Void
@EnvironmentObject var watchlistManager: WatchlistManager
@EnvironmentObject var liveNowManager: LiveNowManager
@State private var player: AVPlayer?
var body: some View {
GeometryReader { geometry in
ZStack {
// Video Player
if let videoURL = event.fullVideoPath(),
FileManager.default.fileExists(atPath: videoURL.path) {
VideoPlayer(player: player)
.frame(width: geometry.size.width, height: geometry.size.height)
.onAppear {
initializePlayer(with: videoURL)
handlePlayback()
}
.onChange(of: isActive) { _ in
handlePlayback()
}
.onDisappear {
cleanupPlayer()
}
} else {
// Error Placeholder
Rectangle()
.fill(Color.black.opacity(0.8))
.frame(width: geometry.size.width, height: geometry.size.height)
.overlay(
Text("Unable to play video")
.foregroundColor(.white)
.font(.headline)
)
}
// Gradient Overlay at the Top
VStack {
LinearGradient(
gradient: Gradient(colors: [.black.opacity(0.7), .clear]),
startPoint: .top,
endPoint: .bottom
)
.frame(height: 150)
Spacer()
}
.edgesIgnoringSafeArea(.top)
// Event Title + Subtitle
VStack(alignment: .leading, spacing: 4) {
Text(event.name ?? "Unknown Event")
.font(.title2)
.fontWeight(.bold)
.foregroundColor(.white)
Text("\(event.genre ?? "Genre") • \(event.time ?? "Time")")
.font(.subheadline)
.foregroundColor(.white.opacity(0.8))
}
.padding([.top, .leading], 16)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
// Buttons at Bottom-Right
VStack(spacing: 12) {
// Like Button
ActionButton(
systemName: liveNowManager.likedEvents.contains(event.id ?? "") ? "heart.fill" : "heart",
action: { toggleLike() },
accessibilityLabel: liveNowManager.likedEvents.contains(event.id ?? "") ? "Unlike" : "Like"
)
Text("\(liveNowManager.likesCount[event.id ?? ""] ?? 0)")
.font(.caption)
.foregroundColor(.white)
// Watchlist Button
ActionButton(
systemName: watchlistManager.isInWatchlist(event: event) ? "checkmark.circle" : "plus.circle",
action: { toggleWatchlist(for: event) },
accessibilityLabel: watchlistManager.isInWatchlist(event: event) ? "Remove from Watchlist" : "Add to Watchlist"
)
// Profile Button
ActionButton(
systemName: "person.crop.circle",
action: { /* Profile Action */ },
accessibilityLabel: "Profile"
)
// Comments Button
ActionButton(
systemName: "bubble.right",
action: { onCommentButtonTapped() },
accessibilityLabel: "Comments"
)
// Location Button
ActionButton(
systemName: "mappin.and.ellipse",
action: { /* Map Action */ },
accessibilityLabel: "Location"
)
}
.padding(.trailing, 16)
.padding(.bottom, 75)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomTrailing)
}
}
}
// MARK: - Player Management
private func initializePlayer(with videoURL: URL) {
if player == nil {
player = AVPlayer(url: videoURL)
}
}
private func handlePlayback() {
guard let player = player else { return }
if isActive {
player.play()
} else {
player.pause()
}
}
private func cleanupPlayer() {
player?.pause()
player = nil
}
// MARK: - Actions
private func toggleWatchlist(for event: CustomEvent) {
if watchlistManager.isInWatchlist(event: event) {
watchlistManager.removeFromWatchlist(event: event)
} else {
watchlistManager.addToWatchlist(event: event)
}
}
private func toggleLike() {
liveNowManager.toggleLike(for: event.id ?? "")
}
}