Reputation: 107
So I'm very new to swift so I might be getting this all wrong.
I'm learning to work with combine so I used the playground to log at an interval like so
var cancellable:AnyCancellable? = Timer.publish(every: 1, on: .main, in: .default)
.autoconnect()
.sink {
print($0)
}
PlaygroundPage.current.needsIndefiniteExecution = true
It's very simple and it works like I expect it to, printing a log every second.
Now when I create a new iOS project in Xcode it doesn't seem to work and I can't figure out why. From a blank project, I simply added this in the ContentView
struct ContentView: View {
func test() {
var cancellable: AnyCancellable?
cancellable = Timer.publish(every: 1, on: .main, in: .default)
.autoconnect()
.sink {
print($0)
}
}
var body: some View {
VStack {
Text("Hello, world!")
.padding()
}
}
init() {
test()
}
}
All of a sudden, it doesn't work and the log won't print. I'm sure it's something dumb that I'm not understanding but I've been looking at this forever now. My real case is with a network call that is not running so I tried simplifying as much as I can and this is as simple as I could get.
Any help appreciated!
Thanks!
Upvotes: 1
Views: 922
Reputation: 52585
There's a couple of things going on here:
Your cancellable
is immediately going out of scope, so it's not being stored. Change it to an @State property on your View instead.
SwiftUI is really picky about what can/can't happen inside init()
of Views. Two options to deal with this:
a) Move it to onAppear
b) Move it to the init() of an @ObservableObject
Working example:
struct ContentView: View {
@State var cancellable : AnyCancellable?
func test() {
cancellable = Timer.publish(every: 1, on: .main, in: .default)
.autoconnect()
.sink {
print($0)
}
}
var body: some View {
VStack {
Text("Hello, world!")
.padding()
}.onAppear {
test()
}
}
}
ObservableObject version:
class ViewModel : ObservableObject {
private var cancellable : AnyCancellable?
init() {
cancellable = Timer.publish(every: 1, on: .main, in: .default)
.autoconnect()
.sink {
print($0)
}
}
}
struct ContentView: View {
var vm = ViewModel()
var body: some View {
VStack {
Text("Hello, world!")
.padding()
}
}
}
Upvotes: 2
Reputation: 539
You’re not calling the function. You need to set the cancellable as a property on your view in this scenario.
Upvotes: 0