tauri icon indicating copy to clipboard operation
tauri copied to clipboard

[docs] How to properly use async methods in a Tauri plugin?

Open InkSha opened this issue 1 month ago • 3 comments

I’m developing a Tauri plugin to access the iOS photo library. Before accessing the library, I need to request authorization from the user:

class func requestAuthorization(for accessLevel: PHAccessLevel) async -> PHAuthorizationStatus

requestAuthorization is an asynchronous API. When I try to mark my plugin method as async, I get an EXC_BAD_ACCESS error. Even marking the default ping method as async causes the same issue:

@objc public func ping(_ invoke: Invoke) async throws {
    let args = try invoke.parseArgs(PingArgs.self)
    invoke.resolve(["value": args.value ?? ""])
}

I saw PR #14148 added async method support and tried adapting my code based on the discussion in the PR, but it still doesn’t work:

@objc public func ping(_ invoke: Invoke) async throws {
    let args = try invoke.parseArgs(PingArgs.self)
    do {
        invoke.resolve(["value": args.value ?? ""])
    } catch {
        invoke.reject("failed \(error.localizedDescription)")
    }
}

Or:

private func _ping(_ invoke: Invoke) async throws {
    let args = try invoke.parseArgs(PingArgs.self)
    do {
        invoke.resolve(["value": args.value ?? ""])
    } catch {
        invoke.reject("failed \(error.localizedDescription)")
    }
}

@objc public func ping(_ invoke: Invoke) throws {
    Task {
        try await self._ping(invoke)
    }
}

InkSha avatar Dec 02 '25 06:12 InkSha

Tauri info:

[✔] Environment
    - OS: Mac OS 15.4.1 x86_64 (X64)
    ✔ Xcode Command Line Tools: installed
    ✔ Xcode: 16.2
    ✔ rustc: 1.86.0 (05f9846f8 2025-03-31)
    ✔ cargo: 1.86.0 (adf9b6ad1 2025-02-28)
    ✔ rustup: 1.28.1 (f9edccde0 2025-03-05)
    ✔ Rust toolchain: stable-x86_64-apple-darwin (default)
    - node: 22.15.0
    - pnpm: 10.10.0
    - yarn: 1.22.22
    - npm: 10.9.2

[-] Packages
    - tauri 🦀: 2.9.4
    - tauri-build 🦀: 2.5.3
    - wry 🦀: 0.53.5
    - tao 🦀: 0.34.5
    - @tauri-apps/api  ⱼₛ: 2.9.0 (outdated, latest: 2.9.1)
    - @tauri-apps/cli  ⱼₛ: 2.9.4 (outdated, latest: 2.9.5)

[-] Plugins

[-] App
    - build-type: bundle
    - CSP: unset
    - frontendDist: ../dist
    - devUrl: http://192.168.10.120:1420/
    - framework: Svelte
    - bundler: Vite

[-] iOS
    - Developer Teams: xxx, xxx

InkSha avatar Dec 02 '25 06:12 InkSha

I saw that PR #13895 added the run_mobile_plugin_async method. I modified the existing code as follows:

// mobile.rs
// ...
    pub async fn ping(&self, payload: PingRequest) -> crate::Result<PingResponse> {
        self.0
            .run_mobile_plugin_async("ping", payload)
            .await
            .map_err(Into::into)
    }
// ...
// commands.rs
#[command]
pub(crate) async fn ping<R: Runtime>(
    app: AppHandle<R>,
    payload: PingRequest,
) -> Result<PingResponse> {
    app.my_plugin().ping(payload).await
}

But it still doesn’t work properly.

InkSha avatar Dec 02 '25 07:12 InkSha

swift info:

swift-driver version: 1.115.1 Apple Swift version 6.0.3 (swiftlang-6.0.3.1.10 clang-1600.0.30.1) Target: x86_64-apple-macosx15.0

InkSha avatar Dec 03 '25 01:12 InkSha