Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does using a function as a closure retain self?

I'm having trouble tracking down a retain cycle. I think it's to do with the way I subscribe to events. Pseudo code is like this:

override func viewDidLoad() {
   func handleEvent() {
     self.doSomething()
   }

   subscribe("eventName", block: handleEvent)
}

deinit {
    unsubscribe("eventName")
} 

Will this create a retain cycle to self / my ViewController? And if so, how can I get around it? If I was using a closure, I could use [weak self], but since I'm passing a function, is there anyway to use a [weak self] equivalent?

like image 486
Roland Rabien Avatar asked Dec 20 '17 17:12

Roland Rabien


2 Answers

Long story short, your code does retain a reference. (handleEvent->viewDidLoad->self), http://blog.xebia.com/function-references-in-swift-and-retain-cycles/ has some general strategies to avoid the issue. My recommendation would be to create a function reference, rather than declaring a function:

let eventHandler: () -> () = { [weak self] in 
    self?.doSomething() 
}
subscribe("eventName", block: eventHandler)
like image 74
GetSwifty Avatar answered Nov 09 '22 23:11

GetSwifty


If you reference a property or method from inside your class it'll create a retain cycle.

class SomeClass {
  val a: (block: (() -> ()) -> ()) = ...

  func run() {
     func b() {
        print("Hello, World!")
     }

     func c() {
        self.someMethod()
     }

     func d() { [weak self] 
        self?.someMethod()
     }

     a(block: b) // no retain cycle
     a(block: c) // retain cycle
     a(block: d) // no retain cycle
  }

  func someMethod() {
     print("Hello, World!")
  }
}
like image 26
Antlip Dev Avatar answered Nov 10 '22 00:11

Antlip Dev