ObservableObject
@ObservedObject
가 되기 위해서는 반드시 ObservableObject 프로토콜을 따르는 클래스여야 합니다.
- 각 프로퍼티 값이 바뀌었을 때 제대로 업데이트가 된 것을 모니터링하려면 해당 프로퍼티에는
@Published
를 붙여서 퍼블리셔로 쓸 수 있도록 해야 합니다.
class HomeVM: ObservableObject {
@Published var isNeedToReload = false {
didSet {
guard isNeedToReload == true else { return }
coffeeMenu.shuffle()
events.shuffle()
isNeedToReload = false
}
}
@Published var coffeeMenu: [CoffeeMenu] = [
CoffeeMenu(image: Image("coffee"), name: "아메리카노"),
CoffeeMenu(image: Image("coffee"), name: "드립커피"),
CoffeeMenu(image: Image("coffee"), name: "카푸치노"),
CoffeeMenu(image: Image("coffee"), name: "콜드브루"),
CoffeeMenu(image: Image("coffee"), name: "아인슈페너"),
CoffeeMenu(image: Image("coffee"), name: "에스프레소"),
CoffeeMenu(image: Image("coffee"), name: "아이스 아메리카노")
]
@Published var events: [Event] = [
Event(image: Image("coffee"), title: "제주도 한정 메뉴", description: "제주도 한정 음료가 출시되었습니다. 꼭 드셔보세요!"),
Event(image: Image("coffee"), title: "여름 한정 메뉴", description: "여름에는 시원한 아이스 커피~ 무더운 여름에 어울리는 아이스 커피를 드셔보세요.")
]
}
@ObservedObject
- observable 객체를 구독하는 property wrapper
- observable 객체가 변경되면 뷰에 업데이트 시켜주는 기능
struct HomeView: View {
@ObservedObject var viewModel = HomeVM()
var body: some View {
ScrollView(.vertical) {
HomeHeaderView(isNeedToReload: $viewModel.isNeedToReload)
MenuSuggestionSectionView(coffeeMenu: $viewModel.coffeeMenu)
Spacer(minLength: 32)
EventSectionView(events: $viewModel.events)
}
}
}
@Published
@Published
를 사용하여 선언된 프로퍼티는
ObservableObject를 구현한 클래스 내에서 사용되어야 합니다. (구조체 X)
@Published
는 property wrapper로, 값의 변경을 관찰하고 구독자에게 알릴 수 있는 기능을 제공합니다.
- 사용하는 쪽에서
$
기호를 사용하여 퍼블리셔에 접근할수 있습니다.
@Binding
@Binding
을 사용하면 상위 뷰에서 전달된 값을 하위 뷰에서 수정하고 업데이트할 수 있습니다.
enum HeaderButton {
case refresh
case new
case coupon
case bell
var buttonName: String {
switch self {
case .refresh:
return "arrow.triangle.2.circlepath"
case .new:
return "mail"
case .coupon:
return "ticket"
case .bell:
return "bell"
}
}
static var buttonSize: CGFloat {
return 16
}
}
struct HomeHeaderView: View {
@Binding var isNeedToReload: Bool
var body: some View {
VStack(spacing: 16) {
HStack(alignment: .top) {
Text("\(User.shared.userName)님~\n반갑습니다! 😄")
.font(.largeTitle)
.frame(maxWidth: .infinity, alignment: .leading)
Button {
isNeedToReload = true
} label: {
Image(systemName: HeaderButton.refresh.buttonName)
}
}
HStack {
Button {
print("New")
} label: {
Image(systemName: HeaderButton.new.buttonName)
.foregroundColor(.secondary)
Text("What's New")
.foregroundColor(.primary)
.font(.system(size: HeaderButton.buttonSize, weight: .semibold))
}
Button(action: {
print("Coupon")
}) {
Image(systemName: HeaderButton.coupon.buttonName)
.foregroundColor(.secondary)
Text("Coupon")
.foregroundColor(.primary)
.font(.system(size: HeaderButton.buttonSize, weight: .semibold))
}
Spacer()
Button(action: {
print("Bell")
}) {
Image(systemName: HeaderButton.bell.buttonName)
.foregroundColor(.secondary)
}
}
}
.padding(16)
}
}