[docs] How to properly use async methods in a Tauri plugin?
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)
}
}
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
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.
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