我有一个带有动画卡顿的应用程序,我已将其提炼为以下复制品:
struct ContentView: View {
var body: some View {
ZStack {
AnimatingCircle()
Button("Trigger animation stutter") {
Task {
await MyActor().go()
}
}
}
}
}
private struct AnimatingCircle: View {
@State var shouldAnimate = false
var body: some View {
Circle()
.fill(.red)
.animation(.easeInOut.repeatForever(autoreverses: true)) {
$0.scaleEffect(shouldAnimate ? 1.5 : 0.5)
}
.onAppear {
shouldAnimate = true
}
}
}
final actor MyActor {
let captureSession = AVCaptureSession()
func go() {
let microphone = AVCaptureDevice.DiscoverySession(
deviceTypes: [.microphone],
mediaType: .audio,
position: .unspecified
).devices.first!
captureSession.addInput(try! AVCaptureDeviceInput(device: microphone))
captureSession.addOutput(AVCaptureAudioDataOutput())
captureSession.startRunning()
}
}
点击按钮时,圆圈动画中有非常明显的卡顿现象。我已经验证我所做的所有 AVFoundation 调用都在后台线程上。我不知道如何解决这个问题。
首先,AVFoundation 代码怎么可能干扰动画?这是否意味着 AVFoundation 工作中的某些内容正在分派回主线程?
第二,有什么解决这个问题的想法吗?
点击此处查看动画结果(动画很烦人):
更新1
我很欣赏对我使用任务和参与者的审查,但这不是原因。此代码也出现了相同的错误:
Button("Trigger animation stutter") {
DispatchQueue.global().async {
go()
}
}
func go() {
let captureSession = AVCaptureSession()
let microphone = AVCaptureDevice.DiscoverySession(
deviceTypes: [.microphone],
mediaType: .audio,
position: .unspecified
).devices.first!
captureSession.addInput(try! AVCaptureDeviceInput(device: microphone))
captureSession.addOutput(AVCaptureAudioDataOutput())
captureSession.startRunning()
}
@State var capturing = false
…
Button("Capture") {
capturing.toggle()
}
.task(id: capturing) {
if capturing == false {
return
}
await go()
capturing = false
}
nonisolated func go() async {
let captureSession = AVCaptureSession()
let microphone = AVCaptureDevice.DiscoverySession(
deviceTypes: [.microphone],
mediaType: .audio,
position: .unspecified
).devices.first!
captureSession.addInput(try! AVCaptureDeviceInput(device: microphone))
captureSession.addOutput(AVCaptureAudioDataOutput())
captureSession.startRunning()
}
try? await Task.sleep(forever) // up to you max time
}