Last active
February 23, 2023 18:54
-
-
Save albertbori/b7998b5d625fc2c93cfe31ccda3f49bf to your computer and use it in GitHub Desktop.
SwiftUI willSet vs didSet onReceive
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Credit: Michael LaRandeau (@mlarandeau) | |
import SwiftUI | |
import Combine | |
import PlaygroundSupport | |
class ValueProvider: ObservableObject { | |
private let didSetSubject = CurrentValueSubject<Int, Never>(0) | |
@Published var value: Int = 0 { | |
didSet { | |
didSetSubject.send(value) | |
} | |
} | |
var didSetPublisher: AnyPublisher<Int, Never> { | |
didSetSubject.eraseToAnyPublisher() | |
} | |
func randomize() { | |
value = Int.random(in: 0..<1000) | |
} | |
} | |
struct TestView: View { | |
@StateObject var valueProvider = ValueProvider() | |
@State var incrementor: Int = 0 | |
var body: some View { | |
print("## Body") | |
return VStack(spacing: 20) { | |
Text("\(valueProvider.value)") | |
// If you use valueProvider.didSetPublisher here instead of $value, the onReceive closure gets called multiple times. | |
.onReceive(valueProvider.$value) { | |
print("## Update Value: \($0)") | |
// If you use the `didSetPublisher` above in onReceive and uncomment the line below, you will trigger an infinite loop | |
// incrementor += 1 | |
} | |
Text("\(incrementor)") | |
Button("Change Number") { | |
valueProvider.randomize() | |
} | |
} | |
} | |
} | |
PlaygroundPage.current.setLiveView(TestView()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment