Skip to main content

Integrate a Flutter app into your macOS project

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)

#

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.

  2. Remove the Flutter pod from your Podfile

    MyApp/Podfile
    ruby
    pod 'FlutterMacOS', :podspec => '/path/to/MyApp/Flutter/[build mode]/FlutterMacOS.podspec'
    
  3. Run pod install.

Organize your projects relative to each other

#

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.

The example directory structure resembles the following:

  • my_flutter_app/
    • macos/
    • lib/
      • main.dart
  • MyNativeApp/
    • MyNativeApp.xcodeproj/

Integrate with Swift Package Manager

#
  1. Build the FlutterNativeIntegration Swift package

    Within your Flutter application or module, run the following command:

    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.

  2. Add FlutterNativeIntegration to your Xcode project

    1. In the Project navigator, right click on your project and select Add Files to "MyNativeApp"...

    2. Navigate to and select the generated FlutterNativeIntegration Swift package and click Add.

    3. Select Reference files in place and click Finish.

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

      Relative location of FlutterNativeIntegration shown in Xcode's File inspector.

      Relative location of FlutterNativeIntegration shown in Xcode's File inspector.

    5. Navigate to your target's General tab and add FlutterNativeIntegration under Frameworks, Libraries, and Embedded Content. FlutterNativeIntegration under Frameworks, Libraries, and Embedded Content.

      FlutterNativeIntegration under Frameworks, Libraries, and Embedded Content.

  3. 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
      
    2. 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.

      Setting `FLUTTER_BUILD_MODE` for custom configurations under **Build Settings**.

      Setting FLUTTER_BUILD_MODE for custom configurations under Build Settings.

    3. For Debug configurations only, set the following build settings:

      ENABLE_APP_SANDBOX=YES
      ENABLE_INCOMING_NETWORK_CONNECTIONS=YES
      RUNTIME_EXCEPTION_ALLOW_JIT=YES
      
      Set **Allow JIT** (RUNTIME_EXCEPTION_ALLOW_JIT) to **YES** in the target's **Build Settings** for **Debug** configurations only.

      Set Allow JIT (RUNTIME_EXCEPTION_ALLOW_JIT) to YES in the target's Build Settings for Debug configurations only.

    4. (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
      
  4. Add Pre-action Run Script to Scheme

    1. Open Product > Scheme > Edit Scheme... > Build (in left side bar) > Pre-action > + > New Run Script Action

    2. Select your project in the Provide build settings from dropdown.

    3. Set the script to the following:

      /bin/sh $FLUTTER_SWIFT_PACKAGE_OUTPUT/Scripts/flutter_integration.sh prebuild
      
    Pre-action Run Script in scheme editor.

    Pre-action Run Script in scheme editor.

  5. Add new run script build phase to your target

    1. Navigate to your target's Build Phases > + > New Run Script Phase

    2. Set the script to the following:

      /bin/sh $FLUTTER_SWIFT_PACKAGE_OUTPUT/Scripts/flutter_integration.sh assemble
      
    3. Uncheck Based on dependency analysis

    4. Add the following to Input File Lists:

      $(FLUTTER_SWIFT_PACKAGE_OUTPUT)/Scripts/FlutterAssembleInputs.xcfilelist
      
    New Run Script Build Phase under Build Phases.

    New Run Script Build Phase under Build Phases.

Next steps

#

You can now add a Flutter screen to your existing macOS app.