Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set a weak reference to a closure/function in Swift?

In HMSegmentedControl, I'd like to set the segmentedControl.indexChangeBlock to an instance method to handle the action. The official example is: https://github.com/HeshamMegid/HMSegmentedControl/blob/master/HMSegmentedControlExample/HMSegmentedControlExample/ViewController.m (Line 63 ~ 68), but that's Objective-C.

In Swift, functions are first class citizens. So I wanna set an instance method to this block property.
But my code would lead to a circular reference, it seems that I should define a weak reference:

class ExampleVC: UIViewController {
    var segmentedControlIndex: Int = 0

    override func viewDidLoad() {
      let segmentedControl3 = HMSegmentedControl(sectionImages: ... , sectionSelectedImages: ... )
      segmentedControl3.frame = ...
      segmentedControl3.indexChangeBlock = someInstanceMethod
    }

    func someInstanceMethod(index: Int) {
      segmentedControlIndex = index
    }
}

However, I cannot define a weak reference to a non-class type. What can I do? Is it legal to do this?

like image 924
WildCat Avatar asked Nov 19 '14 10:11

WildCat


2 Answers

[unowned self] is dangerous. What this does is to tell the runtime 'Assume self has not been released, don't worry about checking.' If self does get released in the meantime, your application will SEGFAULT.

In this case, { [weak self] in self?.someInstanceMethod($0) } will break the reference cycle, and turns into a no-op if self is released.

[weak self] is always safe, while [unowned self] can introduce app crashes if you modify other areas of your code (like view hierarchy, for example)...

like image 188
Andrew Theken Avatar answered Oct 01 '22 21:10

Andrew Theken


Instead of defining weak reference to the closure, you should use "Capture List" in the closure.

segmentedControl3.indexChangeBlock = { [unowned self] in self.someInstanceMethod($0) }

As far as I know, this is the only way to avoid strong reference cycles.

like image 34
rintaro Avatar answered Oct 01 '22 20:10

rintaro