The problem is the presence of the reference to alert
within your UIAlertAction
closure:
alert.addAction(UIAlertAction(title: "Delete Image", style: .destructive, handler: { (action) in
alert.dismiss(animated: true, completion: nil)
}))
This is not only not needed (alerts are dismissed automatically, so calling dismiss
yourself is redundant and potentially problematic), but this reference to alert
within this closure is also introducing a strong reference cycle between the alert controller, the alert action, the closure, and then back to the alert controller.
Worse, when you add a reference to self
in there:
alert.addAction(UIAlertAction(title: "Delete Image", style: .destructive, handler: { (action) in
alert.dismiss(animated: true, completion: nil)
self.exampleObj.vehicleImages.remove(at: indexPath.row)
}))
Now this strong reference cycle between the alert controller and its alert action is now introducing a strong reference to self
, your view controller, which will prevent its properties from being deallocated either.
So just remove these alert
references from within the closures, and the problem will go away:
alert.addAction(UIAlertAction(title: "Delete Image", style: .destructive) { _ in
self.exampleObj.vehicleImages.remove(at: indexPath.row)
})
alert.addAction(UIAlertAction(title: "Return", style: .default))
If you want, you could also make self
a weak
reference:
alert.addAction(UIAlertAction(title: "Delete Image", style: .destructive) { [weak self] _ in
self?.exampleObj.vehicleImages.remove(at: indexPath.row)
})
That way, even if you accidentally introduced a strong reference cycle between the alert controller and its actions, at least self
wouldn’t get caught up in that strong reference cycle. (But it’s worth noting that [weak self]
is not enough to solve the strong reference cycle, but just keeps self
from being involved. You really want to remove those alert
references to avoid the strong reference cycle in the first place.)
FWIW, you can use the “Debug Memory Graph” feature to find what is keeping a strong reference to your object, trace that back, and ultimately if you use the “Malloc stack” feature, you can see precisely where this root strong reference was established. In this case, I presented an alert controller (with that strong reference to both alert
and self
in the closure), then dismissed the view controller in question, tapped on the “Debug Memory Graph” button, and it shows us that ExampleObj
, the view controller, the alert controller, and the alert action are all still in memory:

It’s admittedly tough to follow that graph, but I focus on objects that I created, and I can trace it back from the ExampleObj
to the view controller to the alert action, and even to the line of code where alert
created the strong reference to the view controller. I’ve added those arrows to show how I tracked it back. All of this admittedly doesn’t tell you how to fix the problem, but it lets you track it back, at which point you have a head start in diagnosing the issue.