Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to weak reference a function passed as a parameter

Tags:

ios

swift

I have a strongly referenced model in my view controller that has a function listenToQueue which "listens" to my Firebase database for real time updates. Whenever an update occurs, it passes back an object to my view controller, which then calls a function. Here is my code:

eventModel.listenToQueue { [weak self] queuer in
    self?.queuerDidChange(queuer: queuer)
}

This works. However, originally my code looked like this:

eventModel.listenToQueue(updateHandler: queuerDidChange)

This caused a retain cycle between the model and the view controller. However, that code looks cleaner, so I'm wondering if there's a way to pass the queuerDidChange function via a weak reference to self? I tried this already, but the retain cycle is still there:

weak var weakSelf = self
eventModel.listenToQueue(updateHandler: weakSelf?.queuerDidChange)

Is it possible to do what I want, or shall I just stick to the code I've got?

like image 380
Tometoyou Avatar asked May 29 '18 10:05

Tometoyou


2 Answers

I noticed this in one of my apps. I like the look of passing in the method itself, but I also had to use the weak reference technique you mentioned.

This makes sense, I think, because method implementations are held on the class itself, and self is bound to that implementation when classes are instantiated. Therefore a method will always have a strong reference to self.

And in Swift, function parameters are strongly referenced. I don’t think there’s a way to pass any parameter using a weak reference.

like image 82
ABeard89 Avatar answered Nov 16 '22 00:11

ABeard89


weak var weakSelf = self
eventModel.listenToQueue(updateHandler: weakSelf?.queuerDidChange)

Above code is the same code as:

eventModel.listenToQueue(updateHandler: queuerDidChange)

Because you declare weakSelf and use it immediately. weakSelf?.queuerDidChange has no relation to weakSelf, instead it already contains reference to self itself. I assume queuerDidChange member function. So the only way to avoid retain cycle is what you call the dirty way.

eventModel.listenToQueue { [weak self] queuer in
    self?.queuerDidChange(queuer: queuer)
}
like image 34
Orkhan Alikhanov Avatar answered Nov 16 '22 02:11

Orkhan Alikhanov