3

I have a retain cycle when defining a closure as a variable.

The variable is defined as below:

public class MyCell: UICollectionViewCell {
 public var callback: ((MyCell)->Void)?
}

If I use delegates instead of closures, the retain cycle disappears, but I would like to know how can it be defined with closures for future cases.

I tried to set callback variable as weak, but, as I suppose, weak attribute can only be applied to class and class-bound protocol types.

EDIT

Usage:

class CustomController: UIViewController {
 private func onActionOccurs(_ cell: MyCell) {
 cell.backgroundColor = .red // For example
 }
 // After dequeuing the cell:
 {
 cell.callback = onActionOccurs(_:)
 }
}

Thanks

asked Aug 1, 2018 at 9:06
6
  • check this stackoverflow.com/questions/49302197/… Commented Aug 1, 2018 at 9:12
  • 1
    Add weak self as argument? Commented Aug 1, 2018 at 9:13
  • If the callback argument is the instance itself, then MyCell can be changed to weak self like @JoakimDanielson said. Commented Aug 1, 2018 at 9:14
  • 1
    why passing MyCell as argument to the block ? No need of this, wherever you assigning the block variable, you can capture cell. Commented Aug 1, 2018 at 9:19
  • can you post how are you using this cell closure? Commented Aug 1, 2018 at 9:20

1 Answer 1

6

If you don't need to use self, then you can use the cell itself, and modifying your closure implementation in cell like this

public class MyCell: UICollectionViewCell {
 public var callback: (()->Void)?
}

then you can use it, like this example

class CustomController: UIViewController {
 private func onActionOccurs(_ cell: MyCell) {
 cell.backgroundColor = .red // For example
 }
 // After dequeuing the cell:
 {
 cell.callback = {
 cell.backgroundColor = .red // For example
 }
 }
}

but if you need to use a ViewController method then you need to use the [weak self] capture list If you need use UIViewController methods

class CustomController: UIViewController {
 private func onActionOccurs(_ cell: MyCell) {
 cell.backgroundColor = .red // For example
 }
 // After dequeuing the cell:
 {
 cell.callback = { [weak self] in
 guard let self = self else { return }
 self.viewControllerMethod()
 }
 }
}
Marko
2,9262 gold badges12 silver badges19 bronze badges
answered Aug 1, 2018 at 9:36
Sign up to request clarification or add additional context in comments.

2 Comments

Anyone knows why it stays in memory if we use like this? cell.callback = onActionOccurs(_:) . I understand that it uses self for somecases but some are not using even self functions or methods. Still stay if we don't use like Reinier's.
Because if you use cell.callback = onActionOccurs(_:), cell will hold the reference from UIViewController, it is a retain cycle. Reinier's idea callback is holding a closure in stack memory only, it will be destroyed after function call.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.