Thomas Thomas - 6 days ago 5
iOS Question

Swift - Function as Variable with Self Reference

I've made a struct to hold data for my

UITableViewCell
s that looks like so:

struct CellData {
var title: String
var action: () -> Void
init(title: String, action: () -> Void) {
self.title = title
self.action = action
}
}


And in my
TableViewController
, I'm setting it up like this:

lazy var buttonCells: [CellData] = [
CellData(
title: "Button 1",
action: {
**self.doSomething()**
}
),
CellData(
title: "Button 2",
action: {
**self.doSomethingElse()**
}
)
]


However, the use of
self
inside the action causes it so that the
TableViewController
isn't
deinitialized
when the controller is dismissed (the
deinit
function isn't called). When I remove the
self
references, and replace it with something else, the
TableViewController
is
deinitialized
just fine. How can I go about fixing this abandoned memory issue?

Answer

Change your action definitions to use a capture group:

action: {
  [weak self] in

  guard let strongSelf = self else {
    return
  }
  strongSelf.doSomething()
}

What the [weak self] capture group declaration does is to convert self to a weak variable inside the block. If the owning object gets deallocated while the block is waiting to be called it gets passed nil instead.

Then once inside the block the guard statement tries to map the weak self definition to a strong local variable. If self is nil, it exits. If not, strongSelf contains an unwrapped strong reference to self and you proceed as normal.

Comments