1

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!

2 Answers 2

2

There's a couple of things going on here:

  1. Your cancellable is immediately going out of scope, so it's not being stored. Change it to an @State property on your View instead.

  2. 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() } } } 
Sign up to request clarification or add additional context in comments.

Comments

0

You’re not calling the function. You need to set the cancellable as a property on your view in this scenario.

2 Comments

I'm calling the function in init() {test()}
I missed that part. You still need to retain the cancellable. It gets deinitialized immediately because you’re not assigning it to anything outside the scope of the function (e.g., setting it as a property on your view)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.