Passing func as func arg retains self

I'm not sure if I get your exact use case, but if you do this:

socket.on("event", handler: self.eventHandler)

… this is equivalent to:

socket.on("event") { self.eventHandler($0) }

… then you'll create a retain cycle if self owns the socket, since it registers a closure which strongly captures self. The reason it has to capture self is that the event handler is an instance method, and may in its body use self. It it equivalent to this:

socket.on("event") { Self.eventHandler(self)($0) }

But if you instead do:

socket.on("event") { [weak self] in self?.eventHandler($0) }

… it may seem like it is equivalent, but it is not. It is a no-op which is silently dropping events when self goes away.

I totally see how it must be like this, but I wish there would be syntax to make this a little more ergonomic. This is particularly true when the function takes several arguments. Then it it tedious to keep writing: { [weak self] in self.eventHander($0, $1, $2, $3) } instead of just passing self.eventHandler as a simple function reference.

It is possible to exploit the fact that instance methods really are just curried static functions on the type, and write a wrapper function weakify that takes a static function and an instance (that it captures weakly). You can then replace self.eventHandler with weakify(Self.eventHandler). Notice the uppercase S.

1 Like