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

Offen Anfängerfreundlich
#3,943 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
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

Beitragsleitfaden öffnen

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

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.