Jawad Ali
Jawad Ali

Reputation: 14397

Closure Capture Memory Leak issue with UITableView

In willDisplay method, I get UIImage and IndexPath from a callback closure. I am using tableView inside that closure. Should I need to make that tableView weak to avoid possible memory leaks, or is it not an issue to use strong tableView?

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    guard let cell = cell as? ArtistTableViewCell else { return }
    guard let imageUrl = cell.viewModel.artistImage() else { return }

    // Download image callback closure returns UIImage, IndexPath, and error
    ImageDownloadService.shared.downloadImage(imageUrl,indexPath:indexPath) { [weak tableView] (image, index, error) in
        DispatchQueue.main.async {
            guard let getIndexPath = index else { return }
            guard let getImage = image else { return }
            guard let getCell = tableView?.cellForRow(at: getIndexPath) as? ArtistTableViewCell else { return }

            getCell.setArtistImage(getImage)
        }
    }
}

Upvotes: 0

Views: 971

Answers (3)

wajahat
wajahat

Reputation: 11

Locale variables are not captured by closure as they are within the same scope, so you don't need to make tableview as weak reference.

Upvotes: 1

vadian
vadian

Reputation: 285079

It’s not necessary to capture tableView explicitly because it’s provided as local variable in the first parameter of the willDisplay method.

Therefore it will not cause a memory leak.

There is a simple rule: Don’t capture anything which is locally accessible inside the method.

Feel free to prove it with Instruments.

Upvotes: 2

giorashc
giorashc

Reputation: 13713

weak is preferred. If you retain the tableView and dismiss the view controller while it downloads an image the table view object (and its cells) won't be deallocated until the call download finishes. (however no retain cycle will occur)

Upvotes: 0

Related Questions