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