SwiftUI에서 View와 Model Binding (part3: @EnvironmentObject) - boostcamp-2020/Project01-A-User-Event-Collector GitHub Wiki
음악 플레이어 앱을 만들다보면
특정 노래를 touch 하면 "현재 재생목록"에 추가가 되야합니다
원하는 것!
그러면 "현재 재생목록"은 어디에 있어야하고, 어떻게 접근을 해야할까요?
@StateObject로 현재 재생을 관리할 viewmodel을 만들고
Part2에서 해왔듯, @ObservedObject를 통해서 서로가 공유하게 만들수도 있는데, 이렇게하면 viewmodel이 필요하지 않은곳에서 받으면서 넘겨주게 됩니다
이러한 상황을 대비해서 애플은 @EnvironmentObject을 만들었습니다
WWDC에서 소개한 영상을 빌려오자면 더 쉽게 이해할수 있을 것같네요
그럼 바로 코드로 가보겠습니다
struct TrackCellView: View {
let track: Track
var didToggleFavorite: (() -> Void)?
var body: some View {
HStack {
Button(action: {
}, label: {
TrackInfoView(title: track.title, artist: track.artist)
})
위의 코드는 노래 cellView하나에대한 내용입니다.
위의 사진에서 파란색 테두리의 부분을 눌렀을때 노래를 재생하게 하고 싶습니다
해당 부분을 Button으로 만들어주고, action에서 현재 track을 재생큐
그러면 먼저 현재 재생 그리고 현재 재생 큐를 관리해줄 view model을 보여드리자면
ViewModel
class PlayerViewModel: ObservableObject {
@Published var currentTrack = Track(id: 1, title: "Dynamite", artist: "방탄소년단", isFavorite: true)
@Published var queue = [Track]()
func updateWith(track: Track) {
currentTrack = track
if queue.contains(where: {$0.id == track.id}) {
queue.removeAll(where: {$0.id == track.id})
}
queue.append(track)
}
}
그러면 다시 TrackCellView로 돌아가서 PlayerViewModel
를 추가할건데,
EnvironmentObject
property wrapper를 쓰겠습니다.
struct TrackCellView: View {
let track: Track
'''
@EnvironmentObject var playerViewModel: PlayerViewModel
그리고 Button의 action에서 viewmodel에게 현재의 track정보를 넘기면도비니다.
struct TrackCellView: View {
'''
var body: some View {
HStack {
Button(action: {
playerViewModel.updateWith(track: track)
}, label: {
TrackInfoView(title: track.title, artist: track.artist)
})
그러면 environment object는 어디에서 지정해주면될까요?
PlayerViewModel
이 필요할 곳에게 모두 뿌려주고 싶을경우에는
@StateObject var playerViewModel = PlayerViewModel()
TabView {
TodayView()
.tabItem {
Image(systemName: "1.square.fill")
Text("First")
}
.overlay(NowPlayingView(viewModel: playerViewModel), alignment: .bottom)
}
.environmentObject(playerViewModel)
를 넣어서 적용하면 됩니다.