swiftgrand-central-dispatch

What happens to the outer dispatch context when you call .sync from .async?


I came across this code from a previous developer, and don't understand the comment.

It seems to imply that using the outer DispatchQueue.main.async call will satisfy Apple's requirement to use the main queue to modify the UIImageView.

My Question: I understand that the main queue is being blocked because it's waiting for a synchronous response from the inner queue. But doesn't this approach invalidate the enforcement of calling the ImageView APIs on the main queue? It's explicitly not the main queue anymore.

    private let imageViewQueue = DispatchQueue(label: "com.company.imageViewQueue")
    private var imageView: UIImageView?
    
    ...
    
    func updateImageView(viewer: UIImageView) {
        // have to do this on the main queue as well AND make sure we guard our viewer
        DispatchQueue.main.async {
            self.imageViewQueue.sync {
                self.imageView = viewer
            }
        }
    }

Thanks for any help you can provide in understanding what's going on here.


Solution

  • You are correct that the use of imageViewQueue means that the line self.imageView = viewer is not being done on the main queue. However, the line self.imageView = viewer does not need to be done on the main queue since you are not updating the UI with that line. You are simply updating a local property. So the code is doubly wrong.

    I would remove imageViewQueue and all of its uses. Just ensure that all attempts to read or set self.imageView are done on the main queue. Then code such as self.imageView.image = someImage will be on the main queue and no two threads can update self.imageView.

    // Assume that updateImageView can be called from any queue
    func updateImageView(viewer: UIImageView) {
        DispatchQueue.main.async {
            self.imageView = viewer
        }
    }