Can I create a class instance using DispatchQueue.global().async and have its methods run asynchronously?

I created the playground below to answer my question "If I created a class instance using DispatchQueue.global().async would that class remain in its own asynchronous queue? Even if the main app called one of that classes methods, would that method run asynchronously compared to the main app?

With the sleep line I discovered that the answer is "no."

But I am curious if there is a legit way to do this? Or even if there is, it is considered bad programming?

import UIKit


class MyFunx : NSObject {
    var opsCount = 0
    
    override init() {
        super.init()
    }
    
    func addValues (a: Int, b: Int) {
        let c = a + b
        opsCount += 1
        sleep(1)
    }
}

var firstVar    = 0
var secondVar   = 0

var myFunx : MyFunx?

while secondVar < 100 {
    print ("starting")
    if myFunx == nil {
        print ("making myFunx")
        DispatchQueue.global().async {
            myFunx = MyFunx()
         }
    } else {
        myFunx!.addValues(a: firstVar, b: secondVar)
    }
    firstVar += 1
    secondVar += 1
}
print ("myFunx = \(myFunx)")
print ("\(myFunx?.opsCount)")
print ("exiting")
Answered by SergioDCQ in 702815022

I was informed that this wouldn't work. No matter where the instance of the class was generated, its methods would still run on the main queue by default.

Accepted Answer

I was informed that this wouldn't work. No matter where the instance of the class was generated, its methods would still run on the main queue by default.

Happily it is so. Otherwise, you could not manage UI in any class ! Because UI access must run on the main thread.

No matter where the instance of the class was generated, its methods would still run on the main queue by default.

It’s not the “main queue by default”. Rather, the runtime does not automatically switch queues so these instance methods run on the queue (or other threading context) of the caller. If a method is called from code running on the main queue, it’ll run on the main queue, but if it’s called from code running on some other queue, it’ll run on that queue.

Have you looked at Swift actors? These implement this sort of serialisation where, by default, methods running on the actor are serialised with other methods running on the actor [1].

Actors are part of the overall Swift concurrency effort. For more on this, see our Meet Swift Concurrency page.

Share and Enjoy

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

[1] To be clear, this does not use Dispatch queues under the covers, but rather a custom cooperative thread pool. There’s more info about this in the docs I referenced.

Can I create a class instance using DispatchQueue.global().async and have its methods run asynchronously?
 
 
Q