From ab379942f5df56c0eec754980ad6c5b6005be546 Mon Sep 17 00:00:00 2001 From: agra Date: Mon, 11 May 2026 12:15:14 +0300 Subject: [PATCH] gallery: hop presentLimitedLibraryPicker result to main queue Apple's docs say the iOS 15+ presentLimitedLibraryPicker completion handler runs on "an arbitrary serial dispatch queue". Flutter method-channel results must be invoked on the main queue; calling result(nil) from a background queue produces an iOS native crash on dismiss. Wrap with DispatchQueue.main.async. --- ios/Classes/GalleryPlugin.swift | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ios/Classes/GalleryPlugin.swift b/ios/Classes/GalleryPlugin.swift index d0b5c4f..c0f7e2c 100644 --- a/ios/Classes/GalleryPlugin.swift +++ b/ios/Classes/GalleryPlugin.swift @@ -98,12 +98,17 @@ public class GalleryPlugin: NSObject, NativePlugin, PHPhotoLibraryChangeObserver } result(nil) case "presentLimitedLibraryPicker": - // Just dismissal signal — the actual reload trigger is the - // `ux/gallery/changes` event channel driven by the library - // observer (which fires after iOS commits the new subset). + // Completion handler signals dismissal; reload is driven by + // `ux/gallery/changes` via the library observer (fires after + // iOS commits the new subset). if #available(iOS 15, *), let vc = UxWindow.topViewController { PHPhotoLibrary.shared().presentLimitedLibraryPicker(from: vc) { _ in - result(nil) + // Apple's docs: the completion handler runs on "an + // arbitrary serial dispatch queue". Flutter method- + // channel results must be invoked on the main queue. + DispatchQueue.main.async { + result(nil) + } } } else if #available(iOS 14, *), let vc = UxWindow.topViewController { PHPhotoLibrary.shared().presentLimitedLibraryPicker(from: vc)