There is a technique that is useful 1 when converting apps to Swift Concurrency.

Fire off work to another actor and wait for it to complete

func someNonisolatedFunc() async {
   await MainActor.run {
      // do something on the MainActor 
   }

   doSomethingElse()
}

It is provided for MainActor, but isn’t available on actors you create yourself.

Not fair!

I dug around and found a way to make this available on custom actors.

Extension

This is an extension that will allow any Global Actor to initiate a run command similar to MainActor. I took the signature from the MainActor definition itself.

extension GlobalActor {
    public static func run<T>(resultType: T.Type = T.self, body: @MainActor @Sendable () throws -> T) async rethrows -> T where T : Sendable {
        try await body()
    }
}

This allows us to use the run func in the same way MainActor does.

func someNonisolatedFunc() async {
   await CustomActor.run {
      // do something NOT on the MainActor 
   }

   doSomethingElse()
}

This shouldn’t be heavily used. Although it can be tempting, there is almost always a better way to get similar behavior. But I’ve seen this solve a number of issues devs have faced in legacy code.

  1. This is frequently a bad idea. But can be appropriate in some cases.