🍏/SwiftUI + Combine
[SwiftUI] iOS13에서 onChange(of:perform:) 을 사용하고 싶을 때
eungding
2021. 9. 3. 01:23
728x90
반응형
[ 이슈 ]
Deployment Target이 iOS 13인 앱에서 value change를 감지하기 위해
onChange(of:perform:) 를 사용하려고 했으나 onChange는 iOS 14부터 지원되는 것이였습니다,,,
애플의 Picker 를 예제로 대응책을 살펴보겠습니다!
방법 1 ) onReceive(_:perform:) 는 iOS 13부터 가능하므로 이것을 써준다.
onReceive에 Publisher 타입을 넘겨줘야하므로 Just 로 감싸줘야하는데,
이를 위해 import Combine 해줘야합니다.
import SwiftUI
import Combine
enum Flavor: String, CaseIterable, Identifiable {
case chocolate
case vanilla
case strawberry
var id: String { self.rawValue }
}
struct SomeView: View {
@State private var selectedFlavor = Flavor.chocolate
var body: some View {
Picker("Flavor", selection: $selectedFlavor) {
Text("Chocolate").tag(Flavor.chocolate)
Text("Vanilla").tag(Flavor.vanilla)
Text("Strawberry").tag(Flavor.strawberry)
}
.pickerStyle(SegmentedPickerStyle())
.onReceive(Just(selectedFlavor), perform: { value in
print(value)
})
}
}
방법 2) extension 을 만든다.
import Combine 해주기도 싫고 iOS14+ 에서는 onReceive말고 onChange 쓰고 싶은데, iOS 버전 분기해주기도 싫고... 할 때
extension을 만들어서 사용할 수 있습니다.
이 블로그에서 보고 따라해줬습니다.
import SwiftUI
import Combine
extension View {
/// A backwards compatible wrapper for iOS 14 `onChange`
@ViewBuilder func valueChanged<T: Equatable>(value: T, onChange: @escaping (T) -> Void) -> some View {
if #available(iOS 14.0, *) {
self.onChange(of: value, perform: onChange)
} else {
self.onReceive(Just(value)) { (value) in
onChange(value)
}
}
}
}
import SwiftUI
struct SomeView: View {
@State private var selectedFlavor = Flavor.chocolate
var body: some View {
Picker("Flavor", selection: $selectedFlavor) {
Text("Chocolate").tag(Flavor.chocolate)
Text("Vanilla").tag(Flavor.vanilla)
Text("Strawberry").tag(Flavor.strawberry)
}
.pickerStyle(SegmentedPickerStyle())
.valueChanged(value: selectedFlavor, onChange: { value in
print(value)
})
}
}
[ Reference ]
https://betterprogramming.pub/implementing-swiftui-onchange-support-for-ios13-577f9c086c9
반응형