SIGN IN SIGN UP

iOS: Ensure engine is run on the main thread (#191626)

Previously, running a `FlutterEngine` from a background queue silently
gave us an engine whose platform thread was not the main thread. The
first symptom an app sees is an assertion deep inside
`DisplayLinkManager.shared`, which is accurate but confusing and looks
like a bug rather than an intentional precondition.

`MakeThreadHost` adopts the calling thread as the engine's platform/UI
thread. That thread is required to be the main thread for several
reasons:
* it reads UIKit state and runs every plugin and platform channel
callback
* nothing else pumps its run loop

We now assert this via `FML_CHECK` in:
* `createShell:libraryURI:initialRoute:`: covers the `run*` methods and
`FlutterViewController`'s implicit engine
* `spawnWithEntrypoint:libraryURI:initialRoute:entrypointArgs:`: covers
the second and later engines in a `FlutterEngineGroup`.

A spawned engine inherits its spawner's task runners rather than
adopting the calling thread, so the check in `createShell` constrains
every engine in a group.

This also adds an `FML_DCHECK` during engine construction since it reads
`UIApplication` lifecycle state and registers UIKit observers.

This also annotates the Swift-visible entry points `NS_SWIFT_UI_ACTOR`
so that Swift callers get a compile-time error rather than a runtime
abort. `FlutterViewController` doesn't need an annotation since, like
all view controllers, it already inherits main actor isolation from
`UIViewController`.

Issue: https://github.com/flutter/flutter/issues/190909
Related: https://github.com/flutter/flutter/issues/190725
Related: https://github.com/flutter/flutter/issues/165904

No test changes, since these are assertions and unlike GoogleTest,
XCUITest and Swift Testing tests have no death-test. This doesn't add
any additional runtime aborts since `DisplayLinkManager.shared` already
does this; it just pushes them up to where they're actually actionable
by the user, and provides better error messages.

<!--
Thanks for filing a pull request!
Reviewers are typically assigned within a week of filing a request.
To learn more about code review, see our documentation on Tree Hygiene:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
-->


## Pre-launch Checklist

- [X] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [X] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [X] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [X] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [X] I signed the [CLA].
- [X] I listed at least one issue that this PR fixes in the description
above.
- [X] I updated/added relevant documentation (doc comments with `///`).
- [X] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [X] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [X] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

If this change needs to override an active code freeze, provide a
comment explaining why. The code freeze workflow can be overridden by
code reviewers. See pinned issues for any active code freezes with
guidance.

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
C
Chris Bracken committed
cc0c10e2d151dca49fa52638af98a7b3d597776f
Parent: 8bae903
Committed by GitHub <noreply@github.com> on 8/25/2026, 8:54:24 PM