3

I came across a tutorial from raywenderlich were the author gave some good tips on handling threading issues in singleton. But when using closures from within the singleton class he is using 'weak' reference cycle. Is it really required so since the class is a singleton, it should have a single instance always right?

    final class PhotoManager {
      private init() {}
      static let shared = PhotoManager()

      private var unsafePhotos: [Photo] = []

    let concurrentPhotoQueue = DispatchQueue(label: "com.jeesson.googlypuff.photoQueue", attributes: .concurrent)
      var photos: [Photo] {
        var photoCopy:[Photo]!    
        concurrentPhotoQueue.sync {
            photoCopy = self.unsafePhotos
        }
        return photoCopy
      }

      func addPhoto(_ photo: Photo) {

// Do we need 'weak self here.. and why?
        concurrentPhotoQueue.async(flags: .barrier) {[weak self] in
            // 1
            guard let self = self else {
                return
            }
            self.unsafePhotos.append(photo)
            DispatchQueue.main.async { [weak self] in
                //self?.postContentAddedNotification()
            }
        }



      }

    }

The tutorial

mfaani
  • 33,269
  • 19
  • 164
  • 293
Jeesson_7
  • 761
  • 1
  • 11
  • 38
  • 1
    Nothing is gonna happen if you don't use weak self. It is just a good practice. – Shreeram Bhat Oct 08 '19 at 12:45
  • Also see [How can I create a reference cycle using dispatchQueues?](https://stackoverflow.com/questions/56061092/how-can-i-create-a-reference-cycle-using-dispatchqueues) – mfaani Oct 09 '19 at 19:15

2 Answers2

6

In case of DispatchQueue closures don't add any capture list at all, nowhere.

DispatchQueue closures don't cause retain cycles because self doesn't own them.

Basically capture lists inside a singleton object are not needed as the singleton is never going to be deallocated.

vadian
  • 274,689
  • 30
  • 353
  • 361
  • "as the singleton is never going to be deallocated." What if the singleton is to be deallocated upon logout? – mfaani Oct 09 '19 at 18:53
  • @Honey What does *logout* mean? – vadian Oct 09 '19 at 18:56
  • signing out of an app. e.g. you have a singleton which does refresh token. That singleton is no longer needed upon logout/signout – mfaani Oct 09 '19 at 18:58
  • @Honey You cannot deallocate a singleton with the standard `static let shared =` property. In the case you need a *volatile* instance a singleton is not the right choice. – vadian Oct 09 '19 at 19:13
1

Some singleton's lifecycle is tied to App lifecycle. Some singleton's lifecycle is tied to login/logout.

So what if the singleton is to be deallocated upon logout? I think that's a valid case where using [weak self] can be useful, even for a singleton.

Otherwise just as vadian said, DispatchQueue closures don't cause retain cycles because self doesn't own them. For more see here

mfaani
  • 33,269
  • 19
  • 164
  • 293