Xcode warning for call to DispatchQueue.main.sync: Call to method 'asd' in closure requires explicit use of 'self' to make capture semantics explicit

When calling DispatchQueue.main.async or DispatchQueue.main.sync with a call to self without capturing self, I get a compiler error:

Call to method 'asd' in closure requires explicit use of 'self' to make capture semantics explicit

Since I usually use DispatchQueue.main.async, I'm now used to solving this error by capturing self like this:

DispatchQueue.main.async { [self] in
    asd()
}

But this unfortunately doesn't seem to work with DispatchQueue.main.sync:

DispatchQueue.main.async { [self] in
    asd()
}

This gives the compiler warning:

Call to method 'asd' in closure requires explicit use of 'self' to make capture semantics explicit; this is an error in Swift 6

This warning only appears for DispatchQueue.main.sync and not for DispatchQueue.main.async. Why? How can I avoid having to prefix every method call with self. in this case?

  • I forgot to mention that I'm doing this from a background thread:

    DispatchQueue.global().async {
        DispatchQueue.main.async { [self] in
            asd() // no warning or error
        }
        DispatchQueue.main.sync { [self] in
            asd() // warning: Call to method 'asd' in closure requires explicit use of 'self' to make capture semantics explicit; this is an error in Swift 6
        }
    }
    
Add a Comment

Replies

Shouldn't you be using

self?.asd()

in the closure for weak self?

Shouldn't you be using self?.asd() in the closure for weak self?

Not necessarily. One could use

guard let self = self else {
    return
}

to avoid using self?. each time. But I don't need to use weak self in this case.

I boiled your question down to this:

 1 class Test {
 2 
 3     func asd() {
 4     }
 5     
 6     func test() {
 7         DispatchQueue.global().async { [self] in
 8             DispatchQueue.main.async {
 9                 self.asd()
10             }
11             DispatchQueue.main.async { [self] in
12                 asd()
13             }
14             DispatchQueue.main.sync {
15                 self.asd()
16             }
17             DispatchQueue.main.sync { [self] in
18                 asd()
                   ^ Call to method 'asd' in closure requires explicit use of 'self' to make capture semantics explicit; 
                     this is an error in Swift 6
19             }
20         }
21     }
22 }

This is an interesting glitch in the matrix. It’s definitely triggered by the context set up by line 7. Without that, you don’t see the warning.

The immediate fix here is to use an explicit self, as shown by lines 14 through 16. As to why capturing self on line 17 still triggers the warning, I’m not sure. It’s probably worth filing a bug about that. Please post your bug number, just for the record.

Taking a step back, this overall approach is kinda worrying. First, I recommend against using Dispatch global concurrent queues, as explained in Avoid Dispatch Global Concurrent Queues. That’s not triggering this problem — you still see it if you add a serial queue and replace line 7 with self.queue.async — but if you’re in the habit of using global concurrent queues I recommend that you break that habit.

Second, synchronously dispatching to the main queue is a concern because it can block the current thread for long periods of time.

Taking a further step back, if you’re going to spend time working on code like this, I think you’d be much better off investing in Swift concurrency. While it’s still early days yet, it’s already a much better path forward.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

It’s probably worth filing a bug about that. Please post your bug number, just for the record.

I created FB13454498.

First, I recommend against using Dispatch global concurrent queues, as explained in Avoid Dispatch Global Concurrent Queues.

Thank you. While the second WWDC link on the linked page correctly leads to a video, the first link (WWDC 2015 Session 718 Building Responsive and Efficient Apps with GCD) leads to a list of videos where that video cannot be found. Does it still exist?

Second, synchronously dispatching to the main queue is a concern because it can block the current thread for long periods of time.

I know, but that thread needs access to a resource possibly occupied by the main thread before being able to continue with its work.

I think you’d be much better off investing in Swift concurrency.

I'm still supporting macOS 10.13, while Swift concurrency is only available on macOS 10.15.

Does it still exist?

Well, nothing ever disappears from the Internet (-:

Sadly, it’s no longer available from Apple. I’ve managed to resurrect this video a few times, but it keeps getting removed )-: I’ll put this task back on my to-do list.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"