buzsh / SwiftDiffusion

SwiftUI Stable Diffusion implementation using CoreML and PyTorch
GNU General Public License v3.0
158 stars 4 forks source link

refactor: async FilePickerService #3

Closed buzsh closed 7 months ago

buzsh commented 7 months ago

When calling FilePickerService.browseFile() from ContentView, since the function is now annotated with @MainActor, Swift ensures that the call is made on the main thread, which is compatible with SwiftUI's expectations for UI operations.

struct FilePickerService {

  @MainActor // ← necessary for new Swift concurrency
  static func browseForShellFile() async -> String? {
    return await withCheckedContinuation { continuation in
      let panel = NSOpenPanel()
      panel.allowsMultipleSelection = false
      panel.canChooseDirectories = false

      if let shellScriptType = UTType(filenameExtension: "sh") {
        panel.allowedContentTypes = [shellScriptType]
      } else {
        print("Failed to find UTType for .sh files")
        continuation.resume(returning: nil)
        return
      }

      panel.begin { response in
        if response == .OK, let url = panel.urls.first, url.pathExtension == "sh" {
          continuation.resume(returning: url.path)
        } else {
          print("Error: Selected file is not a .sh script.")
          continuation.resume(returning: nil)
        }
      }
    }
  }
}

GPT4 PR feedback:

Starting with Swift concurrency, certain operations, especially those involving the user interface or other main-thread-bound actions, need to be explicitly marked to run on the main thread. This is enforced more strictly in newer versions of Swift (like Swift 6) with the introduction of stricter concurrency checks.

To resolve these errors, you need to ensure that all interactions with NSOpenPanel occur on the main actor. This can be done by marking the asynchronous function or specific code blocks to run on the main actor. Here's how to adjust your FilePickerService: