I think what’s happened here is some bad architecture on my part that the compiler didn’t catch, really.
My Player actor uses another actor called TelemetryManager to do all the telemetry things. I didn't mention it before because I didn't think it was related!
In order for it to do that, it needs to have access to Player's AVPlayer because it observes AVPlayer’s property publishers and also reads AVPlayer’s properties when it’s about to send telemetry.
So (simplifying the code) in Player you have:
let player = AVPlyer()
lazy var telemetryManager = TelemetryManager(player: player)
Even TelemetryManager itself hands off tracking the state of the media being played to yet another actor called VideoStateTracker which also gets passed this AVPlayer.
So somewhere along the line with all this passing around of AVPlayer the actor executor is being changed or shadowed or something. If I don't attach TelemetryManager at all to Player, everything runs fine.
This taught me to stop passing AVPlayer around and:
Have Player do all property observing itself and call functions on TelemetryManager when something it would want to know about happens
Do "constructor injection" instead of passing AVPlayer, i.e. when TelemetryManager is about to fire off a report and needs the current state of AVPlayer, it calls an injected function from Player to get a snapshot of AVPlayer's current state
...and now it all works great!
Post
Replies
Boosts
Views
Activity
Hi Greg,
Yes I've been trying to crate a "pared-down" version to submit a ticket but I can't seem to trigger it. There must be something else in my code that's changing the actor's context somehow?
I'm going to keep adding more and more chunks of code from the original version to the pared-down version until I trigger it, then update here.
Thanks!
Thankfully for a "quick fix" the only thing I had to do was set the Swift language version back to 5, and the error is gone. So, no more emergency :)
Still would love to know what is going on though!
Adding a .buffer before .values was the answer. Thanks for reading!
I'm having the exact same problem on tvOS, iPadOS, and iOS. Not on macOS (non-Catalyst).
The video is also "black with sound" on real devices, too.
Exact same code works perfectly fine when generated from Xcode 14.2
The problem seems to be with AVPlayer.
You can test this quite easily. Start a new Xcode project in Xcode 14.3, put this in your ContentView.swift:
import AVKit
import SwiftUI
let avPlayer = AVPlayer(url: URL(string: "https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_ts/master.m3u8")!)
struct ContentView: View {
var body: some View {
VideoPlayer(player: avPlayer)
.onAppear { avPlayer.play() }
}
}
...and witness the darkness! You could replace VideoPlayer(player:) with a represented AVPlayerViewController or whatever you like, always black video with sound.
Update:
This seems to be a problem with my project itself.
It was originally an Apple TV app which I turned into a multiplatform app later on. I don't think everything got converted properly; my Info tab in Project Settings only has options for Apple TV.
Nothing really to do here except start a new multiplatform project and import all the files from the previous one!
Thanks.
Hi,
Thanks for this! By multiplatform app I mean an app that targets all Apple platforms as described here:
https://developer.apple.com/documentation/xcode/configuring-a-multiplatform-app-target
So I use this feature to target iOS, iPadOS, tvOS, and macOS. I don't do any Android development.
Even so I think what you wrote may be close to the answer anyway. I'll try it. Though note when you start a new Xcode project as a multiplatform app, it doesn't create an Info.plist file for the project. So I guess I'll have to add one to the project and try this.
Thanks!