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

オープン 初心者向け
#3,943 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
Dart
スター
1.9k
フォーク
1.3k
PR マージ指標
30日以内にマージされた PR はありません

説明

## 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.

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

FPPSharePlusPlugin.m の UIActivityViewController の popover 設定から調査を開始し、報告されている iPhone と iPad の動作を比較します。可能であれば iOS 26 でスワイプによる閉じる操作を再現し、その後、sourceView/sourceRect が iPad に対してのみ設定されていること、および既存の iPad の動作が維持されていることを確認します。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
dart, ios, objective-c
領域
mobile-dev
issue の種類
バグ
難易度
2/5
見積もり時間
1〜3時間
活発さ
静か
明瞭さ
明確に書かれている
初心者へのやさしさ
78/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。