diff --git a/sites/docs/src/_includes/docs/add-to-app/ios-project/local-network-privacy-permissions.md b/sites/docs/src/_includes/docs/add-to-app/ios-project/local-network-privacy-permissions.md new file mode 100644 index 00000000000..3775c94d4a0 --- /dev/null +++ b/sites/docs/src/_includes/docs/add-to-app/ios-project/local-network-privacy-permissions.md @@ -0,0 +1,113 @@ +On iOS 14 and later, enable the Dart multicast DNS service in the +**Debug** version of your iOS app. +This adds [debugging functionalities such as hot-reload and DevTools][] +using `flutter attach`. + +:::warning +Never enable this service in the **Release** version of your app. +The Apple App Store might reject your app. +::: + +To set local network privacy permissions only in the Debug version of your app, +create a separate `Info.plist` per build configuration. +SwiftUI projects start without an `Info.plist` file. +If you need to create a property list, +you can do so through Xcode or text editor. +The following instructions assume the default **Debug** and **Release**. +Adjust the names as needed depending on your app's build configurations. + +1. Create a new property list. + + 1. Open your project in Xcode. + + 1. In the **Project Navigator**, click on the project name. + + 1. From the **Targets** list in the Editor pane, click on your app. + + 1. Click the **Info** tab. + + 1. Expand **Custom iOS Target Properties**. + + 1. Right-click on the list and select **Add Row**. + + 1. From the dropdown menu, select **Bonjour Services**. + This creates a new property list in the project directory + called `Info`. This displays as `Info.plist` in the Finder. + +1. Rename the `Info.plist` to `Info-Debug.plist` + + 1. Click on **Info** file in the project list at the left. + + 1. In the **Identity and Type** panel at the right, + change the **Name** from `Info.plist` to `Info-Debug.plist`. + +1. Create a Release property list. + + 1. In the **Project Navigator**, click on `Info-Debug.plist`. + + 1. Select **File** > **Duplicate...**. + You can also press Cmd + Shift + S. + + 1. In the dialog box, set the **Save As:** field to + `Info-Release.plist` and click **Save**. + +1. Add the necessary properties to the **Debug** property list. + + 1. In the **Project Navigator**, click on `Info-Debug.plist`. + + 1. Add the String value `_dartVmService._tcp` + to the **Bonjour Services** array. + + 1. _(Optional)_ To set your desired customized permission dialog text, + add the key **Privacy - Local Network Usage Description**. + + + +1. Set the target to use different property lists for different build modes. + + 1. In the **Project Navigator**, click on your project. + + 1. Click the **Build Settings** tab. + + 1. Click **All** and **Combined** sub-tabs. + + 1. In the Search box, type `plist`. + This limits the settings to those that include property lists. + + 1. Scroll through the list until you see **Packaging**. + + 1. Click on the **Info.plist File** setting. + + 1. Change the **Info.plist File** value + from `path/to/Info.plist` to `path/to/Info-$(CONFIGURATION).plist`. + + + + This resolves to the path **Info-Debug.plist** in **Debug** and + **Info-Release.plist** in **Release**. + + + +1. Remove the **Release** property list from the **Build Phases**. + + 1. In the **Project Navigator**, click on your project. + + 1. Click the **Build Phases** tab. + + 1. Expand **Copy Bundle Resources**. + + 1. If this list includes `Info-Release.plist`, + click on it and then click the **-** (minus sign) under it + to remove the property list from the resources list. + + + +1. The first Flutter screen your Debug app loads prompts + for local network permission. + + Click **OK**. + + _(Optional)_ To grant permission before the app loads, enable + **Settings > Privacy > Local Network > Your App**. + +[debugging functionalities such as hot-reload and DevTools]: /add-to-app/debugging \ No newline at end of file diff --git a/sites/docs/src/content/add-to-app/index.md b/sites/docs/src/content/add-to-app/index.md index 10bbc9e1380..bbd82e6bd8f 100644 --- a/sites/docs/src/content/add-to-app/index.md +++ b/sites/docs/src/content/add-to-app/index.md @@ -1,7 +1,7 @@ --- title: Add Flutter to an existing app shortTitle: Add to app -description: Adding Flutter as a library to an existing Android or iOS app. +description: Adding Flutter as a library to an existing Android, iOS, macOS, or web app. --- ## Add-to-app @@ -17,11 +17,11 @@ the rest can be rendered using existing technology. This method can also be used to run shared non-UI logic by taking advantage of Dart's portability and interoperability with other languages. -Add-to-app is currently supported on Android, iOS, and web. +Add-to-app is currently supported on Android, iOS, macOS, and web. Flutter supports two flavors of add-to-app: -- **Multi-engine**: supported on Android and iOS, allows running one or more +- **Multi-engine**: supported on Android, iOS, and macOS, allows running one or more instances of Flutter, each rendering a widget embedded into the host application. Each instance is a separate Dart program, running in isolation from other programs. Having multiple Flutter instances allows each instance to @@ -72,10 +72,9 @@ various use-cases. Two of the most common use-cases are: -* Auto-build and import the Flutter module by adding a Flutter - SDK hook to your CocoaPods and to your Xcode build phase. -* Build your Flutter module into a generic [iOS Framework][] +* Build your Flutter module into a Swift package for integration into your own build system. +* Auto-build and import the Flutter module using Xcode build phases. * [`FlutterEngine`][ios-engine] API for starting and persisting your Flutter environment independently of attaching a [`FlutterViewController`][]. @@ -90,6 +89,20 @@ See our [add-to-app GitHub Samples repository][] for sample projects in Android and iOS that import a Flutter module for UI. +### Add to macOS applications +* Build your Flutter module into a Swift package + for integration into your own build system. +* Auto-build and import the Flutter module using Xcode build phases. +* [`FlutterEngine`][macos-engine] API for starting and persisting + your Flutter environment independently of attaching a + [`FlutterViewController`][macos-flutterviewcontroller]. +* Swift host apps supported. +* Flutter modules can use [Flutter plugins][] to interact + with the platform. +* Support for Flutter debugging and stateful hot reload by + using `flutter attach` from IDEs or the command line to + connect to an app that contains Flutter. + ### Add to web applications Flutter can be added to any existing HTML DOM-based web app written in any @@ -119,7 +132,7 @@ To add Flutter to an existing app, build it normally, then follow the ## Get started To get started, see our project integration guide for -Android and iOS: +Android, web, iOS, and macOS: + +
+ Web +
+
+ + + @@ -150,14 +171,23 @@ see our API usage guides at the following links: Android - + + +
+ web +
+
+ + + @@ -197,3 +227,5 @@ Web limitations: [maintained by the Flutter team]: {{site.repo.packages}}/tree/main/packages [multiple Flutters]: /add-to-app/multiple-flutters [FlutterView]: https://api.flutter.dev/flutter/dart-ui/FlutterView-class.html +[macos-engine]: {{site.api}}/macos-embedder/interface_flutter_engine.html +[macos-flutterviewcontroller]: {{site.api}}/macos-embedder/interface_flutter_view_controller.html \ No newline at end of file diff --git a/sites/docs/src/content/add-to-app/ios/project-setup-legacy.md b/sites/docs/src/content/add-to-app/ios/project-setup-legacy.md new file mode 100644 index 00000000000..d25ec14b642 --- /dev/null +++ b/sites/docs/src/content/add-to-app/ios/project-setup-legacy.md @@ -0,0 +1,211 @@ +--- +title: Integrate a Flutter module into your iOS project (Legacy) +shortTitle: Integrate Flutter (Legacy) +description: Learn how to integrate a Flutter module into your existing iOS project. +--- + +:::warning + +As of Flutter 3.44, Swift Package Manager (SwiftPM) replaces CocoaPods +as the default dependency manager for iOS and macOS Flutter apps. +CocoaPods is officially in maintenance mode, +and its registry will permanently [become read-only on December 2, 2026][]. + +This guide is preserved for reference only, and will not receive ongoing maintenance. +Please migrate to using Swift Package Manager using the [updated integration guide][]. + +::: + +Flutter UI components can be incrementally added into your existing iOS +application as embedded frameworks. +To embed Flutter in your existing application, +consider one of the following three methods. + +| Embedding Method | Methodology | Benefit | +|---|---|---| +| Use CocoaPods _(Recommended)_ | Install and use the Flutter SDK and CocoaPods. Flutter compiles the `flutter_module` from source each time Xcode builds the iOS app. | Least complicated method to embed Flutter into your app. | +| Use [iOS frameworks][] | Create iOS frameworks for Flutter components, embed them into your iOS, and update your existing app's build settings. | Doesn't require every developer to install the Flutter SDK and CocoaPods on their local machines. | +| Use iOS frameworks and CocoaPods | Embed the frameworks for your iOS app and the plugins in Xcode, but distribute the Flutter engine as a CocoaPods podspec. | Provides an alternative to distributing the large Flutter engine (`Flutter.xcframework`) library. | + +{:.table .table-striped} + +[iOS frameworks]: {{site.apple-dev}}/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WhatAreFrameworks.html + +When you add Flutter to your existing iOS app, +it [increases the size of your iOS app][app-size]. + +For examples using an app built with UIKit, +see the iOS directories in the [add_to_app code samples][]. +For an example using SwiftUI, consult the iOS directory in [News Feed App][]. + +## Development system requirements + +Flutter requires the latest version of Xcode and [CocoaPods][]. + +## Create a Flutter module + +To embed Flutter into your existing application with any method, +create a Flutter module first. +Use the following command to create a Flutter module. + +```console +$ cd /path/to/my_flutter +$ flutter create --template module my_flutter +``` + +Flutter creates module project under `/path/to/my_flutter/`. +If you use the [CocoaPods method][], save the module +in the same parent directory as your existing iOS app. + +[CocoaPods method]: /add-to-app/ios/project-setup-legacy/?tab=embed-using-cocoapods + +From the Flutter module directory, +you can run the same `flutter` commands you would in any other Flutter project, +like `flutter run` or `flutter build ios`. +You can also run the module in [VS Code][] or +[Android Studio/IntelliJ][] with the Flutter and Dart plugins. +This project contains a single-view example version of your module +before embedding it in your existing iOS app. +This helps when testing the Flutter-only parts of your code. + +## Organize your module + +The `my_flutter` module directory structure resembles a typical Flutter app. + + + +- my_flutter/ + - .ios/ + - Runner.xcworkspace + - Flutter/ + - podhelper.rb + - lib/ + - main.dart + - test/ + - pubspec.yaml + + + +Your Dart code should be added to the `lib/` directory. +Your Flutter dependencies, packages, and plugins must be added to the +`pubspec.yaml` file. + +The `.ios/` hidden subfolder contains an Xcode workspace where +you can run a standalone version of your module. +This wrapper project bootstraps your Flutter code. +It contains helper scripts to facilitate building frameworks or +embedding the module into your existing application with CocoaPods. + +:::note + +* Add custom iOS code to your own existing application's + project or to a plugin, not to the module's `.ios/` + directory. Changes made in your module's `.ios/` + directory don't appear in your existing iOS project + using the module, and might be overwritten by Flutter. + +* Exclude the `.ios/` directory from source control as + it's autogenerated. + +* Before building the module on a new machine, + run `flutter pub get` in the `my_flutter` directory. + This regenerates the `.ios/` directory before building + the iOS project that uses the Flutter module. + +::: + +## Embed a Flutter module in your iOS app + +After you have developed your Flutter module, +you can embed it using the methods described +in the table at the top of the page. + +You can run in **Debug** mode on a simulator or a real device, +and **Release** mode on a real device. + +:::note +Learn more about [Flutter's build modes][build modes of Flutter]. + +To use Flutter debugging features such as hot reload, +consult [Debugging your add-to-app module][]. +::: + + + + +{% render "docs/add-to-app/ios-project/embed-cocoapods.md" %} + + + + +{% render "docs/add-to-app/ios-project/embed-frameworks.md" %} + + + + +{% render "docs/add-to-app/ios-project/embed-split.md" %} + + + + + +## Set local network privacy permissions + +{% render "docs/add-to-app/ios-project/local-network-privacy-permissions.md" %} + +## Mitigate known issue with Apple Silicon Macs + +On [Macs running Apple Silicon][apple-silicon], +the host app builds for an `arm64` simulator. +While Flutter supports `arm64` simulators, some plugins might not. +If you use one of these plugins, you might see a compilation error like +**Undefined symbols for architecture arm64**. +If this occurs, +exclude `arm64` from the simulator architectures in your host app. + +1. In the **Project Navigator**, click on your project. + +1. Click the **Build Settings** tab. + +1. Click **All** and **Combined** sub-tabs. + +1. Under **Architectures**, click on **Excluded Architectures**. + +1. Expand to see the available build configurations. + +1. Click **Debug**. + +1. Click the **+** (plus sign). + +1. Select **iOS Simulator**. + +1. Double-click in the value column for **Any iOS Simulator SDK**. + +1. Click the **+** (plus sign). + +1. Type `arm64` in the **Debug > Any iOS Simulator SDK** dialog box. + + + +1. Press Esc to close this dialog box. + +1. Repeat these steps for the **Release** build mode. + +1. Repeat for any iOS unit test targets. + +## Next steps + +You can now [add a Flutter screen][] to your existing iOS app. + +[add_to_app code samples]: {{site.repo.samples}}/tree/main/add_to_app +[add a Flutter screen]: /add-to-app/ios/add-flutter-screen +[Android Studio/IntelliJ]: /tools/android-studio +[build modes of Flutter]: /testing/build-modes +[CocoaPods]: https://cocoapods.org/ +[app-size]: /resources/faq#how-big-is-the-flutter-engine +[VS Code]: /tools/vs-code +[News Feed app]: https://github.com/flutter/put-flutter-to-work/tree/022208184ec2623af2d113d13d90e8e1ce722365 +[Debugging your add-to-app module]: /add-to-app/debugging/ +[apple-silicon]: https://support.apple.com/en-us/116943 +[become read-only on December 2, 2026]: https://blog.cocoapods.org/CocoaPods-Specs-Repo/ +[updated integration guide]: /add-to-app/ios/project-setup \ No newline at end of file diff --git a/sites/docs/src/content/add-to-app/ios/project-setup.md b/sites/docs/src/content/add-to-app/ios/project-setup.md index a4588b477ef..55f6666ee45 100644 --- a/sites/docs/src/content/add-to-app/ios/project-setup.md +++ b/sites/docs/src/content/add-to-app/ios/project-setup.md @@ -1,308 +1,277 @@ --- -title: Integrate a Flutter module into your iOS project +title: Integrate a Flutter app into your iOS project shortTitle: Integrate Flutter -description: Learn how to integrate a Flutter module into your existing iOS project. +description: Learn how to integrate a Flutter app into your existing iOS project. --- -Flutter UI components can be incrementally added into your existing iOS -application as embedded frameworks. -To embed Flutter in your existing application, -consider one of the following three methods. +:::tip New! This guide has been updated to use Swift Package Manager -| Embedding Method | Methodology | Benefit | -|---|---|---| -| Use CocoaPods _(Recommended)_ | Install and use the Flutter SDK and CocoaPods. Flutter compiles the `flutter_module` from source each time Xcode builds the iOS app. | Least complicated method to embed Flutter into your app. | -| Use [iOS frameworks][] | Create iOS frameworks for Flutter components, embed them into your iOS, and update your existing app's build settings. | Doesn't require every developer to install the Flutter SDK and CocoaPods on their local machines. | -| Use iOS frameworks and CocoaPods | Embed the frameworks for your iOS app and the plugins in Xcode, but distribute the Flutter engine as a CocoaPods podspec. | Provides an alternative to distributing the large Flutter engine (`Flutter.xcframework`) library. | +As of Flutter 3.44, Swift Package Manager replaces CocoaPods +as the default dependency manager for iOS and macOS Flutter apps. +CocoaPods is officially in maintenance mode, +and its registry will permanently [become read-only on December 2, 2026][]. -{:.table .table-striped} +The [legacy integration guide][] is preserved for reference, +but will not receive ongoing maintenance. +Please migrate to using Swift Package Manager. -[iOS frameworks]: {{site.apple-dev}}/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WhatAreFrameworks.html +::: -When you add Flutter to your existing iOS app, -it [increases the size of your iOS app][app-size]. +Flutter UI components can be incrementally added +into your existing iOS application using Swift packages. -For examples using an app built with UIKit, -see the iOS directories in the [add_to_app code samples][]. -For an example using SwiftUI, consult the iOS directory in [News Feed App][]. +## Prerequisites -## Development system requirements +* Flutter 3.44 or later +* Xcode 15.0 or later -Flutter requires the latest version of Xcode and [CocoaPods][]. +### Migrate from Legacy Integration (If Applicable) {: #migrate-legacy-integration} -## Create a Flutter module +If you've already integrated Flutter into your iOS app +using CocoaPods or embedded frameworks, +you must first remove that integration +before following the Swift Package Manager instructions below. -To embed Flutter into your existing application with any method, -create a Flutter module first. -Use the following command to create a Flutter module. +
+ Expand to see instructions to migrate from CocoaPods integration -```console -$ cd /path/to/my_flutter -$ flutter create --template module my_flutter -``` + If your app was previously integrated using CocoaPods, + you must first remove the Flutter installation code from your Podfile. -Flutter creates module project under `/path/to/my_flutter/`. -If you use the [CocoaPods method][], save the module -in the same parent directory as your existing iOS app. + 1. Remove Flutter installation code from your Podfile + ```ruby title="MyApp/Podfile" diff + - flutter_application_path = '../my_flutter' + - load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb') -[CocoaPods method]: /add-to-app/ios/project-setup/?tab=embed-using-cocoapods + - install_all_flutter_pods(flutter_application_path) -From the Flutter module directory, -you can run the same `flutter` commands you would in any other Flutter project, -like `flutter run` or `flutter build ios`. -You can also run the module in [VS Code][] or -[Android Studio/IntelliJ][] with the Flutter and Dart plugins. -This project contains a single-view example version of your module -before embedding it in your existing iOS app. -This helps when testing the Flutter-only parts of your code. + - flutter_post_install(installer) if defined?(flutter_post_install) + ``` -## Organize your module + 1. Run `pod install`. +
-The `my_flutter` module directory structure resembles a typical Flutter app. +
+ Expand to see instructions to migrate from embedded frameworks integration - + If your app was previously integrated using frameworks + generated by the `flutter build ios-framework` command, + you must first remove the frameworks from your Xcode project. -- my_flutter/ - - .ios/ - - Runner.xcworkspace - - Flutter/ - - podhelper.rb - - lib/ - - main.dart - - test/ - - pubspec.yaml + 1. Navigate to your target's General tab + and remove all Flutter-related frameworks and libraries + under **Frameworks, Libraries, and Embedded Content**. - - -Your Dart code should be added to the `lib/` directory. -Your Flutter dependencies, packages, and plugins must be added to the -`pubspec.yaml` file. - -The `.ios/` hidden subfolder contains an Xcode workspace where -you can run a standalone version of your module. -This wrapper project bootstraps your Flutter code. -It contains helper scripts to facilitate building frameworks or -embedding the module into your existing application with CocoaPods. + This includes the `App.xcframework`, `Flutter.xcframework`, + `FlutterPluginRegistrant.xcframework`, + and any Flutter plugins' `xcframework` files. -:::note - -* Add custom iOS code to your own existing application's - project or to a plugin, not to the module's `.ios/` - directory. Changes made in your module's `.ios/` - directory don't appear in your existing iOS project - using the module, and might be overwritten by Flutter. + 1. Remove the Flutter pod from your Podfile + ```ruby title="MyApp/Podfile" diff + - pod 'Flutter', :podspec => '/path/to/MyApp/Flutter/[build mode]/Flutter.podspec' + ``` -* Exclude the `.ios/` directory from source control as - it's autogenerated. + 1. Run `pod install`. +
-* Before building the module on a new machine, - run `flutter pub get` in the `my_flutter` directory. - This regenerates the `.ios/` directory before building - the iOS project that uses the Flutter module. +The [legacy integration guide][] is preserved for reference, +but will not receive ongoing maintenance. -::: +### Organize your projects relative to each other {: #organize-projects-relatively} -## Embed a Flutter module in your iOS app +This guide assumes that your existing iOS app +and your Flutter app or module reside in sibling directories. +If you have a different directory structure, +you will need to adjust the example relative paths accordingly. -After you have developed your Flutter module, -you can embed it using the methods described -in the table at the top of the page. +:::note -You can run in **Debug** mode on a simulator or a real device, -and **Release** mode on a real device. +If integrating for the first time, +it's recommended to use a Flutter application (instead of a module). +Run the following command to create a new Flutter application: -:::note -Learn more about [Flutter's build modes][build modes of Flutter]. +```console +flutter create my_flutter_app +``` -To use Flutter debugging features such as hot reload, -consult [Debugging your add-to-app module][]. ::: - - +The example directory structure resembles the following: -{% render "docs/add-to-app/ios-project/embed-cocoapods.md" %} + + - - + -{% render "docs/add-to-app/ios-project/embed-frameworks.md" %} +- my_flutter_app/ + - ios/ + - lib/ + - main.dart +- MyNativeApp/ + - MyNativeApp.xcodeproj/ + - + -{% render "docs/add-to-app/ios-project/embed-split.md" %} + + +- my_flutter_app/ + - .ios/ + - lib/ + - main.dart +- MyNativeApp/ + - MyNativeApp.xcodeproj/ + +## Integrate with Swift Package Manager {: #integrate-with-swiftpm} -## Set local network privacy permissions - -On iOS 14 and later, enable the Dart multicast DNS service in the -**Debug** version of your iOS app. -This adds [debugging functionalities such as hot-reload and DevTools][] -using `flutter attach`. - -:::warning -Never enable this service in the **Release** version of your app. -The Apple App Store might reject your app. -::: - -To set local network privacy permissions only in the Debug version of your app, -create a separate `Info.plist` per build configuration. -SwiftUI projects start without an `Info.plist` file. -If you need to create a property list, -you can do so through Xcode or text editor. -The following instructions assume the default **Debug** and **Release**. -Adjust the names as needed depending on your app's build configurations. - -1. Create a new property list. - - 1. Open your project in Xcode. - - 1. In the **Project Navigator**, click on the project name. - - 1. From the **Targets** list in the Editor pane, click on your app. - - 1. Click the **Info** tab. - - 1. Expand **Custom iOS Target Properties**. - - 1. Right-click on the list and select **Add Row**. - - 1. From the dropdown menu, select **Bonjour Services**. - This creates a new property list in the project directory - called `Info`. This displays as `Info.plist` in the Finder. - -1. Rename the `Info.plist` to `Info-Debug.plist` - - 1. Click on **Info** file in the project list at the left. - - 1. In the **Identity and Type** panel at the right, - change the **Name** from `Info.plist` to `Info-Debug.plist`. - -1. Create a Release property list. - - 1. In the **Project Navigator**, click on `Info-Debug.plist`. - - 1. Select **File** > **Duplicate...**. - You can also press Cmd + Shift + S. - - 1. In the dialog box, set the **Save As:** field to - `Info-Release.plist` and click **Save**. - -1. Add the necessary properties to the **Debug** property list. - - 1. In the **Project Navigator**, click on `Info-Debug.plist`. - - 1. Add the String value `_dartVmService._tcp` - to the **Bonjour Services** array. + 1.

Build the FlutterNativeIntegration Swift package

- 1. _(Optional)_ To set your desired customized permission dialog text, - add the key **Privacy - Local Network Usage Description**. + Within your Flutter application or module, run the following command: - + ```console + flutter build swift-package --platform ios + ``` -1. Set the target to use different property lists for different build modes. + This will generate the following directories: - 1. In the **Project Navigator**, click on your project. + - 1. Click the **Build Settings** tab. + - my_flutter_app/build/ios/SwiftPackages/ + - FlutterNativeIntegration/ (A Swift package) + - Scripts/ (Directory of scripts and other files needed) - 1. Click **All** and **Combined** sub-tabs. + - 1. In the Search box, type `plist`. - This limits the settings to those that include property lists. + You can optionally change the location of this output + with the `--output` flag. - 1. Scroll through the list until you see **Packaging**. + 1.

Add FlutterNativeIntegration to your Xcode project

- 1. Click on the **Info.plist File** setting. + 1. Open your existing iOS app in Xcode. + 1. In the Project navigator, right click on your project + and select **Add Files to "MyNativeApp"...** + 1. Navigate to and select the generated + `FlutterNativeIntegration` Swift package and click **Add**. + 1. Select **Reference files in place** and click **Finish**. + 1. In the File inspector, + verify the **Location** is **Relative to Project**. + If it is not, you'll need to move the Flutter output directory + to be a sibling directory of your native app. - 1. Change the **Info.plist File** value - from `path/to/Info.plist` to `path/to/Info-$(CONFIGURATION).plist`. + - + 1. Navigate to your target's **General** tab + and add `FlutterNativeIntegration` under + **Frameworks, Libraries, and Embedded Content**. + - This resolves to the path **Info-Debug.plist** in **Debug** and - **Info-Release.plist** in **Release**. + 1.

Add build settings

- + 1. In the **Build Settings** tab, + set the location of the Flutter app's Swift package output directory: + ``` + FLUTTER_SWIFT_PACKAGE_OUTPUT=$SRCROOT/../my_flutter_app/build/ios/SwiftPackages + ``` -1. Remove the **Release** property list from the **Build Phases**. + 1. For custom configurations, set the Flutter build mode. - 1. In the **Project Navigator**, click on your project. + Flutter supports three [build modes][]: Debug, Profile, and Release. + The build mode is determined using the `CONFIGURATION`. + If your configuration does not match one of these, + you can set the `FLUTTER_BUILD_MODE` build setting + to one of these values. - 1. Click the **Build Phases** tab. + - 1. Expand **Copy Bundle Resources**. + 1. (Optional) Allow Xcode to re-build your Flutter app. - 1. If this list includes `Info-Release.plist`, - click on it and then click the **-** (minus sign) under it - to remove the property list from the resources list. + Add the below build settings to your target + to allow Xcode to re-build your Flutter app as part of its build. + This allows you to make changes to your Flutter application + without needing to re-run `flutter build swift-package`. + This requires Flutter to be installed on the machine. - + ``` + FLUTTER_APPLICATION_PATH=$SRCROOT/../my_flutter_app + ENABLE_USER_SCRIPT_SANDBOXING=NO + ``` -1. The first Flutter screen your Debug app loads prompts - for local network permission. + :::tip + This only re-builds the Flutter app's code. + If you add new dependencies, + you’ll need to re-run `flutter build swift-package`. + ::: - Click **OK**. + 1.

Add Pre-action Run Script to Scheme

- _(Optional)_ To grant permission before the app loads, enable - **Settings > Privacy > Local Network > Your App**. + 1. Open **Product** > **Scheme** > **Edit Scheme...** + > **Build** (in left side bar) > **Pre-action** > **+** + > **New Run Script Action** -## Mitigate known issue with Apple Silicon Macs + 1. Select your project in the **Provide build settings from** dropdown. -On [Macs running Apple Silicon][apple-silicon], -the host app builds for an `arm64` simulator. -While Flutter supports `arm64` simulators, some plugins might not. -If you use one of these plugins, you might see a compilation error like -**Undefined symbols for architecture arm64**. -If this occurs, -exclude `arm64` from the simulator architectures in your host app. + 1. Set the script to the following: + ``` + /bin/sh $FLUTTER_SWIFT_PACKAGE_OUTPUT/Scripts/flutter_integration.sh prebuild + ``` -1. In the **Project Navigator**, click on your project. + -1. Click the **Build Settings** tab. + 1.

Add New Run Script Build Phase to Target

-1. Click **All** and **Combined** sub-tabs. + 1. Navigate to your target's **Build Phases** + > **+** > **New Run Script Phase** -1. Under **Architectures**, click on **Excluded Architectures**. + 1. Set the script to the following: + ``` + /bin/sh $FLUTTER_SWIFT_PACKAGE_OUTPUT/Scripts/flutter_integration.sh assemble + ``` + 1. Uncheck **Based on dependency analysis** + 1. Add the following to **Input File Lists**: + ``` + $(FLUTTER_SWIFT_PACKAGE_OUTPUT)/Scripts/FlutterAssembleInputs.xcfilelist + ``` -1. Expand to see the available build configurations. + -1. Click **Debug**. + 1.

(Optional) Set LLDB Init File

-1. Click the **+** (plus sign). + Using Flutter's LLDB Init File improves performance + when debugging on physical iOS 26+ devices. -1. Select **iOS Simulator**. + 1. Open **Product** > **Scheme** > **Edit Scheme...** > **Run** (in left side bar). + 1. Set the **LLDB Init File** to the following path: + ``` + $(FLUTTER_SWIFT_PACKAGE_OUTPUT)/Scripts/flutter_lldbinit + ``` -1. Double-click in the value column for **Any iOS Simulator SDK**. + Alternatively, if your scheme already has an LLDB Init File, + you can add Flutter's LLDB file to it. + The path to Flutter's LLDB Init File must be relative + to the location of your project's LLDB Init File. -1. Click the **+** (plus sign). + ``` + command source --relative-to-command-file "../my_flutter_app/build/ios/SwiftPackages/Scripts/flutter_lldbinit" + ``` -1. Type `arm64` in the **Debug > Any iOS Simulator SDK** dialog box. +{:.steps} - +## Set local network privacy permissions {: #local-network-permissions} -1. Press Esc to close this dialog box. +{% render "docs/add-to-app/ios-project/local-network-privacy-permissions.md" %} -1. Repeat these steps for the **Release** build mode. -1. Repeat for any iOS unit test targets. ## Next steps You can now [add a Flutter screen][] to your existing iOS app. -[add_to_app code samples]: {{site.repo.samples}}/tree/main/add_to_app [add a Flutter screen]: /add-to-app/ios/add-flutter-screen -[Android Studio/IntelliJ]: /tools/android-studio -[build modes of Flutter]: /testing/build-modes -[CocoaPods]: https://cocoapods.org/ -[debugging functionalities such as hot-reload and DevTools]: /add-to-app/debugging -[app-size]: /resources/faq#how-big-is-the-flutter-engine -[VS Code]: /tools/vs-code -[News Feed app]: https://github.com/flutter/put-flutter-to-work/tree/022208184ec2623af2d113d13d90e8e1ce722365 -[Debugging your add-to-app module]: /add-to-app/debugging/ -[apple-silicon]: https://support.apple.com/en-us/116943 +[legacy integration guide]: /add-to-app/ios/project-setup-legacy +[become read-only on December 2, 2026]: https://blog.cocoapods.org/CocoaPods-Specs-Repo/ +[build modes]: /testing/build-modes \ No newline at end of file diff --git a/sites/docs/src/content/add-to-app/macos/add-flutter-screen.md b/sites/docs/src/content/add-to-app/macos/add-flutter-screen.md new file mode 100644 index 00000000000..69db3b5c112 --- /dev/null +++ b/sites/docs/src/content/add-to-app/macos/add-flutter-screen.md @@ -0,0 +1,338 @@ +--- +title: Add a Flutter screen to an macOS app +shortTitle: Add a Flutter screen +description: Learn how to add a single Flutter screen to your existing macOS app. +--- + +This guide describes how to add a single Flutter screen to an existing macOS app. + +## Start a FlutterEngine and FlutterViewController + +To launch a Flutter screen from an existing macOS app, +you start a [`FlutterEngine`][] and a [`FlutterViewController`][]. + +:::note +The `FlutterEngine` serves as a host to the Dart VM and your Flutter runtime, +and the `FlutterViewController` attaches to a `FlutterEngine` +to pass input events into Flutter +and to display frames rendered by the `FlutterEngine`. +::: + +The `FlutterEngine` might have the same lifespan +as your `FlutterViewController` or outlive your `FlutterViewController`. + +:::tip +It's generally recommended to pre-warm a long-lived +`FlutterEngine` for your application because: + +* The first frame appears faster when showing the `FlutterViewController`. +* Your Flutter and Dart state will outlive one `FlutterViewController`. +* Your application and your plugins can interact with Flutter + and your Dart logic before showing the UI. +::: + +See [Loading sequence and performance][] +for more analysis on the latency and memory +trade-offs of pre-warming an engine. + +### Create a FlutterEngine + +Where you create a `FlutterEngine` depends on your host app. + + + + +In this example, we create a `FlutterEngine` object +inside a SwiftUI [`Observable`][] object called `FlutterDependencies`. +Pre-warm the engine by calling `run()`, and then inject this object +into a `ContentView` using the `environment()` view modifier. + + ```swift title="MyApp.swift" +import SwiftUI +import FlutterMacOS +// The following library connects plugins with macOS platform code to this app. +import FlutterPluginRegistrant + +@Observable +class FlutterDependencies { + let flutterEngine = FlutterEngine(name: "my flutter engine", project: nil) + init() { + // Runs the default Dart entrypoint with a default Flutter route. + flutterEngine.run(withEntrypoint: nil) + // Connects plugins with macOS platform code to this app. + RegisterGeneratedPlugins(registry: self.flutterEngine) + } +} + +@main +struct MyApp: App { + // flutterDependencies will be injected through the view environment. + @State var flutterDependencies = FlutterDependencies() + var body: some Scene { + WindowGroup { + ContentView() + .environment(flutterDependencies) + } + } +} +``` + + + + +As an example, we demonstrate creating a `FlutterEngine`, +exposed as a property, on app startup in the app delegate. + +```swift title="AppDelegate.swift" +import Cocoa +import FlutterMacOS +// The following library connects plugins with macOS platform code to this app. +import FlutterPluginRegistrant + +@main +class AppDelegate: FlutterAppDelegate { + lazy var flutterEngine = FlutterEngine(name: "my flutter engine", project: nil) + + override func applicationDidFinishLaunching(_ aNotification: Notification) { + flutterEngine.run(withEntrypoint: nil) + RegisterGeneratedPlugins(registry: self.flutterEngine) + } +} +``` + + + + +### Show a FlutterViewController with your FlutterEngine + + + + +The following example shows a generic `ContentView` with a +[`NavigationLink`][] hooked to a flutter screen. +First, create a `FlutterViewControllerRepresentable` +to represent the `FlutterViewController`. +The `FlutterViewController` constructor takes +the pre-warmed `FlutterEngine` as an argument, +which is injected through the view environment. + +```swift title="ContentView.swift" +import SwiftUI +import FlutterMacOS + +struct FlutterViewControllerRepresentable: NSViewControllerRepresentable { + // Flutter dependencies are passed in through the view environment. + @Environment(FlutterDependencies.self) var flutterDependencies + + func makeNSViewController(context: Context) -> FlutterViewController { + return FlutterViewController( + engine: flutterDependencies.flutterEngine, + nibName: nil, + bundle: nil + ) + } + + func updateNSViewController(_ nsViewController: FlutterViewController, context: Context) {} +} + +struct ContentView: View { + var body: some View { + NavigationStack { + NavigationLink("My Flutter Feature") { + FlutterViewControllerRepresentable() + } + } + } +} +``` + +Now, you have a Flutter screen embedded in your macOS app. + +:::note +In this example, your Dart `main()` entrypoint function runs +when the `FlutterDependencies` observable is initialized. +::: + + + + +The following example shows a generic `ViewController` with an +`NSButton` hooked to present a [`FlutterViewController`][]. +The `FlutterViewController` uses the `FlutterEngine` instance +created in the `AppDelegate`. + +```swift title="ViewController.swift" +import Cocoa +import FlutterMacOS + +class ViewController: NSViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + // Make a button to call the showFlutter function when pressed. + let button = NSButton(title: "Show Flutter!", target: self, action: #selector(showFlutter)) + button.frame = CGRect(x: 202, y: 187, width: 160.0, height: 40.0) + self.view.addSubview(button) + } + + @objc func showFlutter() { + let flutterEngine = (NSApplication.shared.delegate as! AppDelegate).flutterEngine + let flutterViewController = + FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil) + self.addChild(flutterViewController) + flutterViewController.view.frame = self.view.bounds + presentAsModalWindow(flutterViewController) + } +} +``` + +Now, you have a Flutter screen embedded in your macOS app. + +:::note +Using the previous example, the default `main()` entrypoint function +of your default Dart library runs +when calling `run` on the `FlutterEngine` created in the `AppDelegate`. +::: + + + + +### _Alternatively_ - Create a FlutterViewController with an implicit FlutterEngine + +As an alternative to the previous example, +you can let the `FlutterViewController` implicitly create +its own `FlutterEngine` without pre-warming one ahead of time. + +This is not usually recommended +because creating a `FlutterEngine` on-demand could introduce a noticeable +latency between when the `FlutterViewController` is presented +and when it renders its first frame. +This could, however, be useful if the Flutter screen is rarely shown, +when there are no good heuristics +to determine when the Dart VM should be started, +and when Flutter doesn't need to persist state between view controllers. + +To let the `FlutterViewController` present without an existing `FlutterEngine`, +omit the `FlutterEngine` construction, +and create the `FlutterViewController` without an engine reference. + + + + +```swift title="ContentView.swift" +// Existing code omitted. +func makeNSViewController(context: Context) -> FlutterViewController { + return FlutterViewController() +} +``` + + + + +```swift title="ViewController.swift" +// Existing code omitted. +func showFlutter() { + let flutterViewController = FlutterViewController() + self.addChild(flutterViewController) + flutterViewController.view.frame = self.view.bounds + presentAsModalWindow(flutterViewController) +} +``` + + + + +See [Loading sequence and performance][] +for more explorations on latency and memory usage. + +## Using the FlutterAppDelegate + +Letting your application's `UIApplicationDelegate` subclass +`FlutterAppDelegate` is recommended but not required. + +The `FlutterAppDelegate` performs functions such as: + +* Forwarding application callbacks such as [`openURLs`][] + to plugins such as [google_sign_in][]. + +### Creating a FlutterAppDelegate subclass + +Creating a subclass of the `FlutterAppDelegate` in UIKit apps was shown +in the [Start a FlutterEngine and FlutterViewController section][]. +In a SwiftUI app, you can create a subclass of the `FlutterAppDelegate` +and annotate it with the [`Observable()`][] macro as follows: + +```swift title="MyApp.swift" +import SwiftUI +import FlutterMacOS + +@Observable +class AppDelegate: FlutterAppDelegate { + let flutterEngine = FlutterEngine(name: "my flutter engine", project: nil) + + override func applicationDidFinishLaunching(_ aNotification: Notification) { + // Runs the default Dart entrypoint with a default Flutter route. + flutterEngine.run(withEntrypoint: nil) + // Used to connect plugins (only if you have plugins + // with macOS platform code). + RegisterGeneratedPlugins(registry: self.flutterEngine) + } +} + +@main +struct MyApp: App { + // Use this property wrapper to tell SwiftUI + // it should use the AppDelegate class for the application delegate + @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate + + var body: some Scene { + WindowGroup { + ContentView() + } + } +} +``` + +Then, in your view, the `AppDelegate` is accessible +through the view environment. + +```swift title="ContentView.swift" +import SwiftUI +import FlutterMacOS + +struct FlutterViewControllerRepresentable: NSViewControllerRepresentable { + // Access the AppDelegate through the view environment. + @Environment(AppDelegate.self) var appDelegate + + func makeNSViewController(context: Context) -> FlutterViewController { + return FlutterViewController( + engine: appDelegate.flutterEngine, + nibName: nil, + bundle: nil + ) + } + + func updateNSViewController(_ nsViewController: FlutterViewController, context: Context) {} +} + +struct ContentView: View { + var body: some View { + NavigationStack { + NavigationLink("My Flutter Feature") { + FlutterViewControllerRepresentable() + } + } + } +} +``` + +[`FlutterEngine`]: {{site.api}}/macos-embedder/interface_flutter_engine.html +[`FlutterViewController`]: {{site.api}}/macos-embedder/interface_flutter_view_controller.html +[Loading sequence and performance]: /add-to-app/performance +[google_sign_in]: {{site.pub}}/packages/google_sign_in +[`openURLs`]: {{site.apple-dev}}/documentation/appkit/nsapplicationdelegate/application(_:open:) +[Start a FlutterEngine and FlutterViewController section]:/add-to-app/macos/add-flutter-screen/#start-a-flutterengine-and-flutterviewcontroller +[`Observable`]: {{site.apple-dev}}/documentation/observation/observable +[`NavigationLink`]: {{site.apple-dev}}/documentation/swiftui/navigationlink +[`Observable()`]: {{site.apple-dev}}/documentation/observation/observable() diff --git a/sites/docs/src/content/add-to-app/macos/project-setup.md b/sites/docs/src/content/add-to-app/macos/project-setup.md new file mode 100644 index 00000000000..be04ea4ea7e --- /dev/null +++ b/sites/docs/src/content/add-to-app/macos/project-setup.md @@ -0,0 +1,204 @@ +--- +title: Integrate a Flutter app into your macOS project +shortTitle: Integrate Flutter +description: Learn how to integrate a Flutter app into your existing macOS project. +--- + +Flutter UI components can be incrementally added +into your existing macOS application using Swift packages. + +## Prerequisites + +* Flutter 3.44 or later +* Xcode 15.0 or later + +### Migrate from legacy integration (if applicable) {: #migrate-legacy-integration} + +If you've already integrated Flutter into your macOS app +using embedded frameworks, +you must first remove that integration +before following the Swift Package Manager instructions below. + +
+ Expand to see instructions to migrate from embedded frameworks integration + + If your app was previously integrated using frameworks + generated by the `flutter build macos-framework` command, + you must first remove the frameworks from your Xcode project. + + 1. Navigate to your target's **General** tab + and remove all Flutter-related frameworks and libraries + under **Frameworks, Libraries, and Embedded Content**. + + This includes the `App.xcframework`, `FlutterMacOS.xcframework`, + `FlutterPluginRegistrant.xcframework`, + and any Flutter plugins' `xcframework` files. + + 1. Remove the Flutter pod from your Podfile + ```ruby title="MyApp/Podfile" diff + - pod 'FlutterMacOS', :podspec => '/path/to/MyApp/Flutter/[build mode]/FlutterMacOS.podspec' + ``` + + 1. Run `pod install`. +
+ +### Organize your projects relative to each other {: #organize-projects-relatively} + +This guide assumes that your existing macOS app +and your Flutter app reside in sibling directories. +If you have a different directory structure, +you will need to adjust the example relative paths accordingly. + +:::note + +If integrating for the first time, +run the following command to create a new Flutter application: + +```console +flutter create my_flutter_app +``` + +::: + +The example directory structure resembles the following: + + + +- my_flutter_app/ + - macos/ + - lib/ + - main.dart +- MyNativeApp/ + - MyNativeApp.xcodeproj/ + + + +## Integrate with Swift Package Manager {: #integrate-with-swiftpm} + + 1.

Build the FlutterNativeIntegration Swift package

+ + Within your Flutter application or module, run the following command: + + ```console + flutter build swift-package --platform macos + ``` + + This generates the following directories: + + + + - my_flutter_app/build/macos/SwiftPackages/ + - FlutterNativeIntegration/ (A Swift package) + - Scripts/ (Directory of scripts and other files needed) + + + + You can optionally change the location of this output + with the `--output` flag. + + 1.

Add FlutterNativeIntegration to your Xcode project

+ + 1. In the Project navigator, right click on your project + and select **Add Files to "MyNativeApp"...** + 1. Navigate to and select the generated + `FlutterNativeIntegration` Swift package and click **Add**. + 1. Select **Reference files in place** and click **Finish**. + 1. In the File inspector, + verify the **Location** is **Relative to Project**. + If it is not, you'll need to move the Flutter output directory + to be a sibling directory of your native app. + + + + 1. Navigate to your target's **General** tab + and add `FlutterNativeIntegration` under + **Frameworks, Libraries, and Embedded Content**. + + + 1.

Add build settings

+ + 1. In the **Build Settings** tab, + set the location of the Flutter app's Swift package output directory: + ``` + FLUTTER_SWIFT_PACKAGE_OUTPUT=$SRCROOT/../my_flutter_app/build/macos/SwiftPackages + ``` + 1. For custom configurations, set the Flutter build mode. + + Flutter supports three [build modes][]: Debug, Profile, and Release. + The build mode is determined using the `CONFIGURATION` value. + If your configuration does not match one of these, + you can set the `FLUTTER_BUILD_MODE` build setting + to one of these values. + + + + 1. For **Debug** configurations only, set the following build settings: + + ``` + ENABLE_APP_SANDBOX=YES + ENABLE_INCOMING_NETWORK_CONNECTIONS=YES + RUNTIME_EXCEPTION_ALLOW_JIT=YES + ``` + + + + 1. (Optional) Allow Xcode to re-build your Flutter app. + + Add the following build settings to your target + to allow Xcode to re-build your Flutter app as part of its build. + This allows you to make changes to your Flutter application + without needing to re-run `flutter build swift-package`. + This requires a Flutter installation on the machine. + + ``` + FLUTTER_APPLICATION_PATH=$SRCROOT/../my_flutter_app + ENABLE_USER_SCRIPT_SANDBOXING=NO + ``` + + :::tip + This only re-builds the Flutter app's code. + If you add new dependencies, + you’ll need to re-run `flutter build swift-package`. + ::: + + 1.

Add Pre-action Run Script to Scheme

+ + 1. Open **Product** > **Scheme** > **Edit Scheme...** + > **Build** (in left side bar) > **Pre-action** > **+** + > **New Run Script Action** + + 1. Select your project in the **Provide build settings from** dropdown. + + 1. Set the script to the following: + ``` + /bin/sh $FLUTTER_SWIFT_PACKAGE_OUTPUT/Scripts/flutter_integration.sh prebuild + ``` + + + + 1.

Add new run script build phase to your target

+ + 1. Navigate to your target's **Build Phases** + > **+** > **New Run Script Phase** + + 1. Set the script to the following: + ``` + /bin/sh $FLUTTER_SWIFT_PACKAGE_OUTPUT/Scripts/flutter_integration.sh assemble + ``` + 1. Uncheck **Based on dependency analysis** + 1. Add the following to **Input File Lists**: + ``` + $(FLUTTER_SWIFT_PACKAGE_OUTPUT)/Scripts/FlutterAssembleInputs.xcfilelist + ``` + + + +{:.steps} + +## Next steps + +You can now [add a Flutter screen][] to your existing macOS app. + +[add a Flutter screen]: /add-to-app/macos/add-flutter-screen +[become read-only on December 2, 2026]: https://blog.cocoapods.org/CocoaPods-Specs-Repo/ +[build modes]: /testing/build-modes \ No newline at end of file diff --git a/sites/docs/src/content/release/breaking-changes/network-policy-ios-android.md b/sites/docs/src/content/release/breaking-changes/network-policy-ios-android.md index f55ed2459ef..39f5a01dd2f 100644 --- a/sites/docs/src/content/release/breaking-changes/network-policy-ios-android.md +++ b/sites/docs/src/content/release/breaking-changes/network-policy-ios-android.md @@ -37,7 +37,7 @@ network policy. See the migration guide below for details. :::important The following only applies to platform native sockets (sockets owned -by the Android and iOS platforms). +by the Android and iOS platforms). Flutter does not enforce any policy at socket level; you would be responsible for securing the connection. If the socket is owned by @@ -73,7 +73,8 @@ Then, add the network configuration to your $project_path/android/app/src/debug/ It is also possible to set the policy per domain. See the Android docuentation for more information. -For iOS, you can follow [these instructions](/add-to-app/ios/project-setup/?tab=embed-using-cocoapods#set-local-network-privacy-permissions) to create a `Info-debug.plist` and put this in: +For iOS, you can follow [these instructions][] to create a `Info-debug.plist` +and put this in: ```xml NSAppTransportSecurity @@ -112,3 +113,4 @@ Relevant PRs: [PR 20218: Plumbing for setting domain network policy]: {{site.repo.engine}}/pull/20218 [Introduce per-domain policy for strict secure connections]: {{site.github}}/dart-lang/sdk/commit/d878cfbf20375befa09f9bf85f0ba2b87b319427 +[these instructions]: /add-to-app/ios/project-setup#local-network-permissions \ No newline at end of file diff --git a/sites/docs/src/data/sidenav/default.yml b/sites/docs/src/data/sidenav/default.yml index 392c6502608..86951c92c4c 100644 --- a/sites/docs/src/data/sidenav/default.yml +++ b/sites/docs/src/data/sidenav/default.yml @@ -618,6 +618,13 @@ permalink: /add-to-app/ios/project-setup - title: Add a single Flutter screen permalink: /add-to-app/ios/add-flutter-screen + - title: Add to an macOS app + permalink: /add-to-app/macos + children: + - title: Set up macOS project + permalink: /add-to-app/macos/project-setup + - title: Add a single Flutter screen + permalink: /add-to-app/macos/add-flutter-screen - title: Add to a web app permalink: /platform-integration/web/embedding-flutter-web - title: Debug embedded Flutter module diff --git a/sites/docs/web/assets/images/docs/development/add-to-app/ios/project-setup-swiftpm/build-phase-run-script.png b/sites/docs/web/assets/images/docs/development/add-to-app/ios/project-setup-swiftpm/build-phase-run-script.png new file mode 100644 index 00000000000..7befb124238 Binary files /dev/null and b/sites/docs/web/assets/images/docs/development/add-to-app/ios/project-setup-swiftpm/build-phase-run-script.png differ diff --git a/sites/docs/web/assets/images/docs/development/add-to-app/ios/project-setup-swiftpm/flutter-build-mode.png b/sites/docs/web/assets/images/docs/development/add-to-app/ios/project-setup-swiftpm/flutter-build-mode.png new file mode 100644 index 00000000000..6edbf8df943 Binary files /dev/null and b/sites/docs/web/assets/images/docs/development/add-to-app/ios/project-setup-swiftpm/flutter-build-mode.png differ diff --git a/sites/docs/web/assets/images/docs/development/add-to-app/ios/project-setup-swiftpm/flutternativeintegration-library.png b/sites/docs/web/assets/images/docs/development/add-to-app/ios/project-setup-swiftpm/flutternativeintegration-library.png new file mode 100644 index 00000000000..2e709c9af34 Binary files /dev/null and b/sites/docs/web/assets/images/docs/development/add-to-app/ios/project-setup-swiftpm/flutternativeintegration-library.png differ diff --git a/sites/docs/web/assets/images/docs/development/add-to-app/ios/project-setup-swiftpm/flutternativeintegration-relative-location.png b/sites/docs/web/assets/images/docs/development/add-to-app/ios/project-setup-swiftpm/flutternativeintegration-relative-location.png new file mode 100644 index 00000000000..e855a1195c6 Binary files /dev/null and b/sites/docs/web/assets/images/docs/development/add-to-app/ios/project-setup-swiftpm/flutternativeintegration-relative-location.png differ diff --git a/sites/docs/web/assets/images/docs/development/add-to-app/ios/project-setup-swiftpm/pre-action.png b/sites/docs/web/assets/images/docs/development/add-to-app/ios/project-setup-swiftpm/pre-action.png new file mode 100644 index 00000000000..ce32a202f33 Binary files /dev/null and b/sites/docs/web/assets/images/docs/development/add-to-app/ios/project-setup-swiftpm/pre-action.png differ diff --git a/sites/docs/web/assets/images/docs/development/add-to-app/macos/project-setup-swiftpm/allow-jit-build-setting.png b/sites/docs/web/assets/images/docs/development/add-to-app/macos/project-setup-swiftpm/allow-jit-build-setting.png new file mode 100644 index 00000000000..153beb53928 Binary files /dev/null and b/sites/docs/web/assets/images/docs/development/add-to-app/macos/project-setup-swiftpm/allow-jit-build-setting.png differ diff --git a/sites/docs/web/assets/images/docs/development/add-to-app/macos/project-setup-swiftpm/flutternativeintegration-relative-location.png b/sites/docs/web/assets/images/docs/development/add-to-app/macos/project-setup-swiftpm/flutternativeintegration-relative-location.png new file mode 100644 index 00000000000..46972d44715 Binary files /dev/null and b/sites/docs/web/assets/images/docs/development/add-to-app/macos/project-setup-swiftpm/flutternativeintegration-relative-location.png differ