Hi @RanLearns!
I was in the same position as you when Apple released beta 4. I was able to fix the issues mainly around the play() being asynchronous now and can throw an error. I don't know if my approach is the standard, one but I'll share it nonetheless.
Dividing the error into two parts -
- Trying to make an async call from a non-async function.
- The call can throw errors, but the function is not handling the error.
For the first part, we can suffix the function with the async
keyword and prefix the call with the await
keyword.
For example, `handlePlayButtonSelected() becomes -
private func handlePlayButtonSelected() async {
if !isPlaying {
if !isPlaybackQueueSet {
player.setQueue(with: album)
isPlaybackQueueSet = true
}
await player.play()
} else {
player.pause()
}
}
We can make the function throw an error and prefix the call with the try
keyword for the second part. So, handlePlayButtonSelected()
finally looks like -
private func handlePlayButtonSelected() async throws {
if !isPlaying {
if !isPlaybackQueueSet {
player.setQueue(with: album)
isPlaybackQueueSet = true
}
try await player.play()
} else {
player.pause()
}
}
Similarly, `handlePlayButtonSelected() can be changed to -
private func handleTrackSelected(_ track: Track, loadedTracks: MusicItemCollection<Track>) async throws {
player.setQueue(with: loadedTracks, startingAt: track)
isPlaybackQueueSet = true
try await player.play()
}
Now, you'll get another error in view where you call these functions. First, in the list where you show the TrackCell
, update the action handleTrackSelected(track, loaded tracks: loadedTracks)
with the following -
Task {
try? await handleTrackSelected(track, loadedTracks: loadedTracks)
}
For the second error in the button in playButtonRow
, update handlePlayButtonSelected
with -
Task {
try? await handlePlayButtonSelected()
}
The third error is due to a change in the searchable
modifier. Now, you've to specify a prompt.
So, replace searchable("Albums", text: $searchTerm)
with -
.searchable(text: $searchTerm, prompt: "Albums")
There are a few warnings as well, mostly related to the use of detach
. You can replace them with Task.detached
.
Lastly, you'll find deprecation warnings related to the setQueue(with:startingAt:)
method. In Xcode 13, Beta 4 added a new instance property, queue
.
We can set this property by using the initializers of the class Queue
. In AlbumDetailView.handleTrackSelected(_:loadedTracks:)
, you can set it as -
private func handleTrackSelected(_ track: Track, loadedTracks: MusicItemCollection<Track>) async throws {
player.queue = .init(for: loadedTracks, startingAt: track)
isPlaybackQueueSet = true
try await player.play()
}
In handlePlayButtonSelected()
, you can set it as -
private func handlePlayButtonSelected() async throws {
if !isPlaying {
if !isPlaybackQueueSet {
player.queue = .init(arrayLiteral: album)
isPlaybackQueueSet = true
}
try await player.play()
} else {
player.pause()
}
}
The last warning is related to the deprecation of the playbackStatus variable. The latest beta offers us with ObservableObject
class MusicPlayer.State
, and we'll use the playbackState
instance property instead. I'm not sure about this one on how to go about observing the value of the playbackStatus
, but here's my approach -
.task {
isPlaying = player.state.playbackStatus == .playing
}
With this, the project is error and warnings-free!