Using async/await with existing non-concurrent code

A global actor MainActor will provide the ability to ensure that something executes on the main thread (I think we've also called it UIActor in some places... MainActor is the better name). You can decorate any function with @MainActor to ensure that it will execute on the main thread, so let's add such a method to note when the pass was signed:

extension ViewController {
  @MainActor func passWasSigned(signed: Data, signature: Data) {
    self.isPassSigned = true
    // set some label in the UI, on the main queue
  }
}

Now our state update is guaranteed to happen on the main thread, so let's write viewWillAppear. I noted that the PKPassLibrary API you used follows the Objective-C conventions for completion-handler methods, so it is automatically imported as async based on SE-0297 that is also under review now. So, let's immediately jump into async-land by creating a detached task in viewWillAppear:

extension ViewController {
  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    Task.runDetached {    
      do {
        let (signed, signature) = await try library.sign(data, using: pass)
        await passWasSigned(signed: signed, signature: signature) // okay, hops over to the main actor to do its work
      } catch {
        // tell the user something went wrong, I hope
      }
    }
  }
}

Now, @asyncHandler is mean to help with exactly these cases. It essentially runs the body of the function in an implicitly-created detached task on the given actor, so we can eliminate some boilerplate:

extension ViewController {
  @MainActor @asyncHandler
  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    do {
      let (signed, signature) = await try library.sign(data, using: pass)
      // hops back to @MainActor now
      isPassSigned = true
      // set some label in the UI, on the main actor
    } catch {
      // tell the user something went wrong, I hope
    }
  }
}

Heh, I appreciate your faith in us, but let's see how the above stacks up ;)

Doug

8 Likes