fluttercommunity / fluttercommunity/plus_plugins
[share_plus] iOS: sourceView set unconditionally on iPhone — on iOS 26 swipe-dismissing the sheet can hang the share() Future and break touch delivery
- Vorherrschende Sprache
- Dart
- Sterne
- 1.9k
- Forks
- 1.3k
- PR-Merge-Kennzahlen
- Keine gemergten PRs in 30 T.
Beschreibung
## Platform
- `share_plus`: 13.2.0 (same code present in 12.x)
- iOS 26.3 – 26.5.2, iPhone (reproduced on iPhone 16e / 17 Pro / 17 Pro Max, simulator and physical devices)
- Flutter 3.44.4
## Description
In `FPPSharePlusPlugin.m`, `popoverPresentationController.sourceView` is assigned **unconditionally**, regardless of `UIUserInterfaceIdiom`:
```objc
activityViewController.popoverPresentationController.sourceView = topViewController.view;
if (!CGRectIsEmpty(origin)) {
activityViewController.popoverPresentationController.sourceRect = origin;
}
```
There is no way to opt out from Dart: even when the caller passes no `sharePositionOrigin`, `sourceView` is still set.
On iPhone this used to be harmless, but on **iOS 26** a non-nil `sourceView` routes `UIActivityViewController` into the popover/anchored presentation path (compact sheet anchored to the Flutter view). When the user dismisses that sheet **interactively** (swipe down — most reliably after visiting a sub-screen such as AirDrop and coming back), the dismissal can end up in a broken state:
1. `completionWithItemsHandler` is **never called** → the `Future` returned by `SharePlus.share()` never completes, and any `await`/`finally` after it is dead.
2. The `UIActivityViewController` can stay `presented` with `isBeingDismissed == true` indefinitely (interrupted interactive dismissal never finishes), or stay presented with its view already detached from the window.
3. Touch delivery inside the app degrades: taps in part of the Flutter UI (in our case the bottom sheet under the share origin) stop being delivered until the presentation stack is rebuilt (e.g., by pushing/popping any route). Instrumentation shows events dying before reaching gesture handlers while the widget tree is healthy.
## Steps to reproduce
1. iPhone with iOS 26.x, any app calling `SharePlus.instance.share(ShareParams(uri: ...))` (no `sharePositionOrigin`).
2. Open the share sheet, optionally enter the AirDrop sub-screen and come back.
3. Dismiss the sheet with a swipe-down gesture.
4. Observe: the `share()` Future often never completes; in a fraction of runs taps around the share origin stop working.
The race is timing-sensitive (roughly 1 in 3 attempts in our testing), the AirDrop detour makes it much more reliable.
## Expected
- `sourceView`/popover configuration only applies on iPad (where `sharePositionOrigin` is genuinely required), or is at least skippable from Dart.
- `completionWithItemsHandler` fires (with `completed == false`) for interrupted interactive dismissals so the returned Future always completes.
## Workaround we ship (vendored fork)
Wrapping the popover configuration in an idiom check fixes the iPhone path while keeping iPad behavior intact:
```objc
BOOL isIpad = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad);
if (isIpad) {
activityViewController.popoverPresentationController.sourceView =
topViewController.view;
if (!CGRectIsEmpty(origin)) {
activityViewController.popoverPresentationController.sourceRect = origin;
}
}
```
The hung-completion part still needs an app-level watchdog on iOS 26 even with this patch (the OS sometimes drops the completion for interrupted dismissals), but the touch-delivery breakage no longer reproduces with `sourceView` unset on iPhone.
Happy to send a PR with the idiom guard if that direction works for the maintainers.
Beitragsleitfaden
Rechercherichtung
Beginne in FPPSharePlusPlugin.m bei der Popover-Konfiguration von UIActivityViewController und vergleiche das gemeldete Verhalten auf iPhone und iPad. Reproduziere das Wischen zum Schließen unter iOS 26, falls verfügbar, und überprüfe anschließend, dass sourceView/sourceRect nur für iPad konfiguriert werden und das bestehende iPad-Verhalten intakt bleibt.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- dart, ios, objective-c
- Bereich
- mobile-dev
- Issue-Typ
- Bug
- Schwierigkeit
- 2/5
- Geschätzter Aufwand
- 1-3 Stunden
- Aktivitätsstatus
- Ruhig
- Klarheit
- Klar beschrieben
- Anfängerfreundlichkeit
- 78/100