Reputation: 175
I am developing an app that uses MPRemoteCommandCenter to control audio reproduction from the lock screen.
The code is inside a @MainActor view-model, part of a SwiftUI project.
The initial code that I need to incorporate is:
commandCenter.playCommand.isEnabled = true
commandCenter.playCommand.addTarget { [unowned self] event in
if !self.isPlaying {
self.playOrPause()
return .success
}
return .commandFailed
}
I have tried this:
commandCenter.playCommand.isEnabled = true
commandCenter.playCommand.addTarget { [unowned self] event in
return await MainActor.run {
if !self.isPlaying {
self.playOrPause()
return .success
}
return .commandFailed
}
}
But still it doesn't compile.
I understand why: the callback method is not marked to be async. Still it expects a value, that I can return only from async code, because I need to wait to re-enter into the main thread.
Can anyone please help me?
Upvotes: 1
Views: 1630
Reputation: 4026
You cannot ask for a sync function to wait for an async. You can have however an async function receiving the returned values from other async closures using withCheckedContinuation()
.
In your case, this is how it might work:
let isSuccessfullyCompleted: Bool = await withCheckedContinuation { continuation in
commandCenter.playCommand.isEnabled = true
commandCenter.playCommand.addTarget { [unowned self] event in
if !self.isPlaying {
self.playOrPause()
continuation.resume(returning: true)
} else {
continuation.resume(returning: false)
}
}
}
With the code above, isSuccessfullyCompleted
will wait for the closure to complete and return a value, before resuming the code. The variable doesn't need to be a Bool
, but the code above needs to run in an async function.
Upvotes: 1