2

I have a viewController that has a collectionView outlet. In the cellForRowAt method I call this code:

guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCell", for: indexPath) as? MediaPhotoCell else {fatalError("Could not initialize cell")}
       cell.configureForMedia(obj, completion: { [weak self](image:UIImage?) in
            if let loadedImage = image {
                    let photo = self?.loadedPhotos[indexPath.row]
                    photo?.image = loadedImage
                    self?.loadedPhotos[indexPath.row] = photo
                    self?.photosViewController?.updateImage(for: photo)
                }
            })
return cell

I've been spending time on learning how to resolve/prevent memory leaks through retain cycles. I added a capture list [weak self] before capturing the value in the closure (image: UIIimage?). My logic is that since viewController owns the collectionview, and that collectionview owns the cell, which has a closure method in it's custom implementation (custom cell), and closure references self, i'm creating a retain cycle if i do not declare self as weak.

Is this necessary? Or is this not necessary if the outlet (the collectionView) is declared as weak?

  • 2
    That is the way I do it! – Daniel Lyon Aug 15 '18 at 17:33
  • 1
    @DanielLyon is absolutely spot on with that. You have avoided a capturing self properly – Erik Aug 15 '18 at 17:40
  • 1
    Thank you so much! Do either of you follow anyone that has a good guide to finding memory leaks/improving app performance? – leahyjwilliam Aug 15 '18 at 17:43
  • @leahyjwilliam I don't have a specific guide but one thing I can recommend is to watch the memory usage graph in Xcode while using the app. If it seems like the memory keeps increasing and never decreases when it should (e.g. when a view controller is dismissed or images are scrolled away in a table view), you might have a memory leak. – Paolo Aug 15 '18 at 17:53
  • It is getting a bit dated but I benefited a great deal from a Ray Wenderlich tutorial https://www.raywenderlich.com/397-instruments-tutorial-with-swift-getting-started – Daniel Lyon Aug 15 '18 at 17:57
  • 1
    It is not clear to me why this is needed. I am unfamiliar with `configureForMedia`, but usually `completion` blocks are not retained indefinitely and are intended to be released after the method's action is taken. In this case, it may be more beneficial to keep a strong reference to `self`. There is no retain cycle here. – Ian MacDonald Aug 15 '18 at 18:06
  • Ian is right, If the block is not being retained by the cell class as a strong property/variable, it's no need to use `weak self`, other people surely just do it without knowing the exact cause – Tj3n Aug 16 '18 at 10:42

1 Answers1

2

Your example works to create a weak reference to self for use in a closure.

As to @IanMacDonald comment about it not being required for your example, he is also correct. So you would only need to do this if self could be nil in the closure.

A good example case for using [weak self] would be for an asynchronous network request, in a view controller where that request is used to populate the view. If the user backs out, we no longer need to populate the view, nor do we need a reference to the view controller.

I really liked this medium article about reference counting in closures.

Daniel Lyon
  • 1,499
  • 10
  • 15