0

I have an actor:

actor MyActor {
    
    let theQueue = OperationQueue()

    init() {

        _ = theQueue.observe(\OperationQueue.operationCount, options: .new) { oq, change in
            print("OperationQueue.operationCount changed: \(self.theQueue.operationCount)")
        }
        
    }

    ....

}

I was trying to get a KVO going to then trigger some type of publisher call that other models in the app could subscribe to and react as needed when the operationCount changes.

I was going to have a function that maybe would set that up, but, as of now, using self in that initializer gives me this warning, which according this this:

https://forums.swift.org/t/proposal-actor-initializers-and-deinitializers/52322

it will turn into an error soon.

The warning I get is this:

Actor 'self' can only be captured by a closure from an async initializer

So, how could I trigger a publisher other models can then react to that would publish the operation queue's operationCount as it changes?

matt
  • 515,959
  • 87
  • 875
  • 1,141
zumzum
  • 17,984
  • 26
  • 111
  • 172
  • Please don't put an answer inside the question. The question should be a question. If you have an alternate answer, give it as an _answer_. – matt Sep 30 '21 at 15:58
  • I thought it would have been useful to others to know since the title says "publish" and that's a keyword related to the combine approach I ended up using. Given that Rob Napier's answer seems acceptable in context I didn't want to post an answer that would contract his. I would have liked to have that addition if I stumbled across this question. But that's just my opinion. Thanks. – zumzum Sep 30 '21 at 16:23
  • It's _fine_ to post an alternate answer. It doesn't contradict the existing / accepted answer. That is how Stack Overflow works: it collects multiple answers to individual questions. You _should_ give your answer as an answer so that it _will_ be useful. – matt Sep 30 '21 at 16:29

1 Answers1

3

You don't need to capture self here. observe sends you the new value (for basically exactly this reason):

_ = theQueue.observe(\OperationQueue.operationCount, options: .new) { oq, change in
    print("OperationQueue.operationCount changed: \(change.newValue!)")
}

Also, oq is theQueue if you need that. If you need self, the typical way to do that is:

observation = observe(\.theQueue.operationCount, options: .new) { object, change in
    // object is `self` here.
}

Just remember that you're outside the actor inside this closure, so calls may need to be async inside a Task.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610