[SwiftUI] EqutableView (feat. POD)
- EqutableView란?
> EqutableView는 이전 값과 비교하여 새 값이 이전 값과 동일한 경우 자식 업데이트를 방지하도록 설계된 뷰입니다.
`iOS 13.0+` `iPadOS 13.0+` `tvOS 13.0` `watchOS 6.0+` `visionOS 1.0+ Beta
[apple-docs-EqutableView](https://developer.apple.com/documentation/swiftui/equatableview)
💡 들어가기 전.
- 아래의 개념에 대한 지식이 반드시 필요함. 필요한 이유는 글 제일 아래에서 설명
- [Plain ol' Data](https://rldd.tistory.com/551)
EqutableView Usage
1. 내가 EqutableView로 만들고자 하는 곳에 Equtable을 채택
struct LuckyBoxStateView: View, Equtable { ... }
2. 사용하는 곳에서
Equtable(content: LuckyBoxStateView(text: text))
or
/// ✅ 요 방식이 선언적이라 더 나음
LuckyBoxStateView(text: text)
.equtable()
예제 시나리오
- 내가 만드는 서비스에 확률형 아이템인 럭키박스가 있다고 가정.
- 럭키박스를 구매시 특정 확률에 따라 배수가 결정.
- 럭키박스 오픈시 결정된 배수가 UI에 나타나는 방식.
✅ Code Smaple
import SwiftUI
enum LuckyBoxState: String {
case state1 = "x10배"
case state2 = "x2배"
case state3 = "x0.5배"
case state4 = "x0.1배"
static func result(number: Double) -> String {
if number < 5 {
return LuckyBoxState.state1.rawValue
} else if number < 15 {
return LuckyBoxState.state2.rawValue
} else if number < 45 {
return LuckyBoxState.state3.rawValue
} else {
return LuckyBoxState.state4.rawValue
}
}
}
struct ContentView: View {
@State private var number: Double = 0
@State private var count: UInt = 0
private let size: CGFloat = 200
var body: some View {
print("count: \(count) | number: \(number)")
return VStack {
LuckyBoxStateView(text: LuckyBoxState.result(number: number))
.equatable()
.frame(width: size, height: size * 2 / 3, alignment: .center)
.background(.blue.opacity(0.5))
.cornerRadius(10)
Button {
number = Double.random(in: 0..<100)
count += 1
} label: {
Text("럭키박스 오픈")
}
Text("당첨번호: \(number)")
Text("오픈차수: \(count)")
}
}
}
struct LuckyBoxStateView: View, Equatable {
var text: String
static func == (lhs: LuckyBoxStateView, rhs: LuckyBoxStateView) -> Bool {
return lhs.text == rhs.text
}
var body: some View {
print("init")
return VStack(alignment: .center) {
Text("🎊 당첨 🎊")
Spacer()
.frame(height: 20)
Text(text)
.font(.system(size: 40, weight: .semibold))
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
- 해당 코드를 실행했을 때의 결과
보다시피 값이 동일할 경우 init을 수행하지 않음.
🚨 여기서 주의해야 하는 점 🚨
이거 진짜 중요함. 경우에 따라서는 EqutableView로 만들어도 작동하지 않는 경우도 존재.
- 만약 LuckyBoxStateView에 member가 POD 타입만 존재하는 경우 경우에는 EqutableView임에도 해당 `static func ==`이 호출되지 않고 LuckyBoxStateView의 init이 호출됩니다.
- non-POD가 하나라도 존재하는 경우 해당 부분은 `static func ==`으로 관리되며 @State와 @Biding의 경우에는 내부에서 자체적으로 `static func ==`을 결정하고 있습니다.
(참고)
https://ios-development.tistory.com/1111