Queryable - Swift package to present SwiftUI views "asynchronously" through continuations

Hey,

I've been working on something for the past few months that allows you to use Swift's concurrency mechanism to trigger any kind of SwiftUI view presentation and await its completion/result, similar to calling an async function, but with UI as the "asynchronous" part.

I'm calling it Queryable: GitHub - SwiftedMind/Queryable: Asynchronous view presentations in SwiftUI

Example

To better explain what it does, here is a simple example:

import SwiftUI
import Queryable

struct ContentView: View {
  // Empty input type and Bool as the result type
  @Queryable<Void, Bool> var buttonConfirmation

  var body: some View {
    Button("Commit", action: confirm)
      .queryableAlert(controlledBy: buttonConfirmation, title: "Really?") { item, query in
          Button("Yes") { query.answer(with: true) }
          Button("No") { query.answer(with: false) }
      } message: {_ in}
  }

  @MainActor
  private func confirm() {
    Task {
      do {
        let isConfirmed = try await buttonConfirmation.query()
        // Do something with the result
      } catch {}
    }
  }
}

This is a view with a single button. When you tap it, an iOS alert should be shown with a "Yes" and a "No" button to confirm or cancel the action. The alert presentation is controlled by a buttonConfirmation property, which completely hides the state logic required to do this.

All you have to do is call buttonConfirmation.query(). from any asynchronous context (doesn't even have to be from within the same view). That function will suspend the current Task, show the alert and then resume with the result, once the user has tapped on one of the buttons. This nicely integrates any kind of UI into asynchronous code. The entire view presentation is compressed into a single function call: query().

This not only works with alert, but also with confirmationDialog, sheet, fullScreenCover and fully custom overlay views.

Get Started

You'll find more information and details in the "Get Started" section of the repository's readme. And if you want to see it used inside an app, have a look at SwiftedMind/Scrumdinger, which is a re-implementation of Apple's SwiftUI tutorial app with an app architecture I'm currently working on for fun (the guys from pointfree had the awesome idea to use Apple's example app and re-implement it using different techniques, so that is my attempt at it :sweat_smile:).

I'm genuinely curious what people think of this. I'm still not completely sure if this entire idea is a terrible anti-pattern or an actually useful tool for building SwiftUI apps.

Have a great day!

5 Likes

I had a similar idea but for App/UIKit and experimented with it in a real application. I liked it a lot since it reduces the need for the delegate pattern or using closures and makes view controller presentation very linear and easy to understand. It makes entire screen flows very quick to implement and the resulting code becomes very clear to the reader without having to jump around the code all the time.

I was surprised I didn't find anyone else with the same idea, not even a thought experiment described anywhere, so I regard it as a very experimental approach with some potential.

1 Like

Yeah, maybe there is a reason nobody has done it before, and I just haven't seen it yet :sweat_smile:. So far, though, it seems to be working fine in the apps I've been building with it.