CINXE.COM
Swift Package Manager for plugin authors | Flutter
<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Swift Package Manager for plugin authors | Flutter</title><link rel="icon" href="/assets/images/branding/flutter/icon/64.png" eleventy:ignore><link rel="apple-touch-icon" href="/assets/images/branding/flutter/logo/flutter-logomark-320px.png" eleventy:ignore><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="theme-color" content="#ffffff"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><meta name="google-site-verification" content="HFqxhSbf9YA_0rBglNLzDiWnrHiK_w4cqDh2YD2GEY4"><script>!function(e,t,a,n){e[n]=e[n]||[],e[n].push({"gtm.start":(new Date).getTime(),event:"gtm.js"});var g=t.getElementsByTagName(a)[0],m=t.createElement(a);m.async=!0,m.src="https://www.googletagmanager.com/gtm.js?id=GTM-ND4LWWZ",g.parentNode.insertBefore(m,g)}(window,document,"script","dataLayer")</script><script>!function(e,a,t,n,c,o,s){e.GoogleAnalyticsObject=c,e[c]=e[c]||function(){(e[c].q=e[c].q||[]).push(arguments)},e[c].l=1*new Date,o=a.createElement(t),s=a.getElementsByTagName(t)[0],o.async=1,o.src="//www.google-analytics.com/analytics.js",s.parentNode.insertBefore(o,s)}(window,document,"script",0,"ga"),ga("create","UA-67589403-1","auto"),ga("send","pageview")</script><meta name="description" content="How to add Swift Package Manager compatibility to iOS and macOS plugins"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:site" content="@flutterdev"><meta property="og:title" content="Swift Package Manager for plugin authors"><meta property="og:url" content="https://docs.flutter.dev/packages-and-plugins/swift-package-manager/for-plugin-authors"><meta property="og:description" content="How to add Swift Package Manager compatibility to iOS and macOS plugins"><meta property="og:image" content="https://docs.flutter.dev/assets/images/flutter-logo-sharing.png" eleventy:ignore><link href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Google+Sans+Text:wght@400;500;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Google+Sans+Mono:wght@400;500;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" rel="stylesheet"><script>window.__CALLBACKS=[]</script><link rel="stylesheet" href="/assets/css/main.css?v=4"></head><body><section id="cookie-notice"><div class="container"><p>docs.flutter.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. <a href="https://policies.google.com/technologies/cookies" target="_blank" rel="noopener">Learn more</a>.</p><button id="cookie-consent" class="filled-button">OK, got it</button></div></section><noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-ND4LWWZ" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript><div id="site-banner" role="alert"><p>Flutter 3.29 is here with a bouquet of performance and fidelity improvements for your apps! <a href="https://medium.com/flutter/whats-new-in-flutter-3-29-f90c380c2317">Learn more</a><br></p></div><header class="site-header"><a href="#document-title" id="skip-to-main" class="filled-button" tabindex="1">Skip to main content</a><nav class="navbar"><div id="site-switcher" class="dropdown"><button class="dropdown-button site-wordmark" aria-expanded="false" aria-controls="site-switcher-menu" aria-label="Switch between Flutter and Dart sites"><img src="/assets/images/branding/flutter/logo/default.svg" alt="Flutter logo" width="28"> <span>Flutter</span> <span class="subtype">Docs</span> <span class="material-symbols" aria-hidden="true">unfold_more</span></button><div class="dropdown-content" id="site-switcher-menu"><nav class="dropdown-menu" role="menu"><ul><li role="presentation"><a href="https://flutter.dev" class="site-wordmark" role="menuitem" title="Flutter homepage" aria-label="Go to the Flutter homepage"><img src="/assets/images/branding/flutter/logo/default.svg" alt="Flutter logo" width="28"> <span>Flutter</span></a></li><li role="presentation"><a href="https://docs.flutter.dev" class="site-wordmark current-site" role="menuitem" aria-current="true" title="Flutter docs homepage" aria-label="Go to the Flutter docs homepage"><img src="/assets/images/branding/flutter/logo/default.svg" alt="Flutter logo" width="28"> <span>Flutter</span> <span class="subtype">Docs</span></a></li><li role="presentation"><a href="https://api.flutter.dev" class="site-wordmark" role="menuitem" title="Flutter API reference" aria-label="Go to the Flutter API reference"><img src="/assets/images/branding/flutter/logo/default.svg" alt="Flutter logo" width="28"> <span>Flutter</span> <span class="subtype">API</span></a></li><li aria-hidden="true" class="dropdown-divider" role="separator"></li><li role="presentation"><a href="https://dart.dev" class="site-wordmark" role="menuitem" title="Dart homepage" aria-label="Go to the Dart homepage"><img src="/assets/images/branding/dart/logo.svg" alt="Dart logo" width="28" height="28"> <span>Dart</span></a></li><li role="presentation"><a href="https://dartpad.dev" class="site-wordmark" role="menuitem" title="DartPad playground" aria-label="Go to the DartPad playground"><img src="/assets/images/branding/dart/logo.svg" alt="Dart logo" width="28" height="28"> <span>DartPad</span></a></li><li role="presentation"><a href="https://pub.dev" class="site-wordmark" role="menuitem" title="pub.dev homepage" aria-label="Go to the pub.dev homepage"><img src="/assets/images/branding/dart/logo.svg" alt="Dart logo" width="28" height="28"> <span>pub.dev</span></a></li></ul></nav></div></div><div class="navbar-contents"><ul class="navbar-nav"><li class="nav-item"><a class="nav-link" href="https://flutter.dev">Homepage</a></li><li class="nav-item"><a class="nav-link" href="https://flutter.dev/community">Community</a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev">Packages</a></li><li class="nav-item"><a class="nav-link" href="https://api.flutter.dev">API reference</a></li></ul><form action="/search/" class="site-header__search"><input class="site-header__searchfield search-field" type="search" name="q" id="q" autocomplete="off" placeholder="Search" aria-label="Search"></form><a href="/search" id="fallback-search-button" class="icon-button" aria-label="Navigate to the docs search page." title="Navigate to the docs search page."><span class="material-symbols" aria-hidden="true">search</span> </a><a id="call-to-action" class="filled-button" href="/get-started/install/">Get started</a> <button id="menu-toggle" class="icon-button" type="button" aria-controls="sidenav" aria-label="Toggle navigation" title="Toggle navigation"><span class="material-symbols" aria-hidden="true">menu</span></button></div></nav></header><div id="site-below-header"><div id="site-main-row"><div id="sidenav" class="site-sidebar"><nav><ul><li class="nav-header">Get started</li><li class="nav-item"><a class="nav-link" href="/get-started/install"><div><span>Set up Flutter</span></div></a></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-3" role="button" aria-expanded="false" aria-controls="sidenav-3"><span>Learn Flutter</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-3"><li class="nav-item"><a class="nav-link" href="/get-started/learn-flutter"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/codelab"><div><span>Write your first app</span></div></a></li><li class="nav-item"><button class="nav-link collapsible" data-toggle="collapse" data-target="#sidenav-3-3" role="button" aria-expanded="true" aria-controls="sidenav-3-3"><span>Learn the fundamentals</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse show" id="sidenav-3-3"><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/dart"><div><span>Intro to Dart</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/widgets"><div><span>Widgets</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/layout"><div><span>Layout</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/state-management"><div><span>State management</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/user-input"><div><span>Handling user input</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/networking"><div><span>Networking and data</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/fundamentals/local-caching"><div><span>Local data and caching</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-3-4" role="button" aria-expanded="false" aria-controls="sidenav-3-4"><span>From another platform?</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-3-4"><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/android-devs"><div><span>Flutter for Android devs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/compose-devs"><div><span>Flutter for Jetpack Compose devs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/swiftui-devs"><div><span>Flutter for SwiftUI devs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/uikit-devs"><div><span>Flutter for UIKit devs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/react-native-devs"><div><span>Flutter for React Native devs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/web-devs"><div><span>Flutter for web devs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/xamarin-forms-devs"><div><span>Flutter for Xamarin.Forms devs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/declarative"><div><span>Introduction to declarative UI</span></div></a></li><li class="nav-item"><a class="nav-link" href="/get-started/flutter-for/dart-swift-concurrency"><div><span>Flutter versus Swift concurrency</span></div></a></li></ul></li><div class="sidenav-divider"></div><li class="nav-item"><a class="nav-link" href="/codelabs"><div><span>Codelabs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook"><div><span>Cookbook</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://github.com/flutter/samples" target="_blank" rel="noopener"><div><span>Demos and samples</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-4" role="button" aria-expanded="false" aria-controls="sidenav-4"><span>Stay up to date</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-4"><li class="nav-item"><a class="nav-link" href="/release/upgrade"><div><span>Upgrade</span></div></a></li><li class="nav-item"><a class="nav-link" href="/release/archive"><div><span>SDK archive</span></div></a></li><div class="sidenav-divider"></div><li class="nav-item"><a class="nav-link" href="/release/whats-new"><div><span>What's new</span></div></a></li><li class="nav-item"><a class="nav-link" href="/release/release-notes"><div><span>Release notes</span></div></a></li><li class="nav-item"><a class="nav-link" href="/release/breaking-changes"><div><span>Breaking changes</span></div></a></li><li class="nav-item"><a class="nav-link" href="/release/compatibility-policy"><div><span>Compatibility policy</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-5" role="button" aria-expanded="false" aria-controls="sidenav-5"><span>App solutions</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5"><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-1" role="button" aria-expanded="false" aria-controls="sidenav-5-1"><span>AI</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-1"><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-1-1" role="button" aria-expanded="false" aria-controls="sidenav-5-1-1"><span>AI Toolkit guide</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-1-1"><li class="nav-item"><a class="nav-link" href="/ai-toolkit"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ai-toolkit/user-experience"><div><span>User experience</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ai-toolkit/feature-integration"><div><span>Feature integration</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ai-toolkit/custom-llm-providers"><div><span>Custom LLM providers</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ai-toolkit/chat-client-sample"><div><span>Chat client sample</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="https://www.youtube.com/watch?v=1AuzJEiHjO4" target="_blank" rel="noopener"><div><span>Build with Google AI Dart SDK (video)</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-2" role="button" aria-expanded="false" aria-controls="sidenav-5-2"><span>Firebase & Firestore</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-2"><li class="nav-item"><a class="nav-link" href="/data-and-backend/firebase"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/docs/flutter" target="_blank" rel="noopener"><div><span>Discover Firebase for Flutter</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://www.youtube.com/watch?v=wUSkeTaBonA" target="_blank" rel="noopener"><div><span>Get to know Firebase for Flutter</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/codelabs/firebase-auth-in-flutter-apps" target="_blank" rel="noopener"><div><span>Add a user authentication flow to a Flutter app using FirebaseUI</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/codelabs/firebase-get-to-know-web" target="_blank" rel="noopener"><div><span>Get to know Firebase for web</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-3" role="button" aria-expanded="false" aria-controls="sidenav-5-3"><span>Games</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-3"><li class="nav-item"><a class="nav-link" href="/resources/games-toolkit"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/games/achievements-leaderboard"><div><span>Add achievements and leaderboards</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/codelabs/build-leaderboards-with-firestore#0" target="_blank" rel="noopener"><div><span>Build leaderboards with Firestore</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/plugins/google-mobile-ads"><div><span>Add advertising</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/games/firestore-multiplayer"><div><span>Add multiplayer support</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/flutter-in-app-purchases" target="_blank" rel="noopener"><div><span>Add in-app purchases</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/codelabs/firebase-auth-in-flutter-apps" target="_blank" rel="noopener"><div><span>Add user authentication</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/docs/crashlytics/get-started?platform=flutter" target="_blank" rel="noopener"><div><span>Debug using Crashlytics</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/flutter-flame-brick-breaker" target="_blank" rel="noopener"><div><span>Intro to Flame with Flutter</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-4" role="button" aria-expanded="false" aria-controls="sidenav-5-4"><span>Monetization</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-4"><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-4-1" role="button" aria-expanded="false" aria-controls="sidenav-5-4-1"><span>Advertising</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-4-1"><li class="nav-item"><a class="nav-link" href="/resources/ads-overview"><div><span>Ads overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/plugins/google-mobile-ads"><div><span>Add advertising</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/admob-ads-in-flutter" target="_blank" rel="noopener"><div><span>Add AdMob ads to your Flutter app</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/admob-inline-ads-in-flutter" target="_blank" rel="noopener"><div><span>Add an AdMob banner and native inline ads</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://developers.google.com/admob/flutter/mediation" target="_blank" rel="noopener"><div><span>Google AdMob mediation</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/packages/interactive_media_ads" target="_blank" rel="noopener"><div><span>Interactive Media Ads SDK</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-4-2" role="button" aria-expanded="false" aria-controls="sidenav-5-4-2"><span>In-app purchases</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-4-2"><li class="nav-item"><a class="nav-link" href="/resources/in-app-purchases-overview"><div><span>In-app purchases overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/flutter-in-app-purchases" target="_blank" rel="noopener"><div><span>Add in-app purchases</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-4-3" role="button" aria-expanded="false" aria-controls="sidenav-5-4-3"><span>Payments</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-4-3"><li class="nav-item"><a class="nav-link" href="/resources/payments-overview"><div><span>Payments overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/packages/pay" target="_blank" rel="noopener"><div><span>Google pay package</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-5" role="button" aria-expanded="false" aria-controls="sidenav-5-5"><span>Maps</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-5"><li class="nav-item"><a class="nav-link" href="https://codelabs.developers.google.com/codelabs/google-maps-in-flutter" target="_blank" rel="noopener"><div><span>Add Google maps to a Flutter app</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://developers.google.com/maps/flutter-package" target="_blank" rel="noopener"><div><span>Google Maps package</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-5-6" role="button" aria-expanded="false" aria-controls="sidenav-5-6"><span>News</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-5-6"><li class="nav-item"><a class="nav-link" href="/resources/news-toolkit"><div><span>Build a news app</span></div></a></li></ul></li></ul></li><li aria-hidden="true"><div class="sidenav-divider"></div></li><li class="nav-header">User interface</li><li class="nav-item"><a class="nav-link" href="/ui"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/widgets"><div><span>Widget catalog</span></div></a></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-10" role="button" aria-expanded="false" aria-controls="sidenav-10"><span>Layout</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-10"><li class="nav-item"><a class="nav-link" href="/ui/layout"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/layout/tutorial"><div><span>Build a layout</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-10-3" role="button" aria-expanded="false" aria-controls="sidenav-10-3"><span>Lists & grids</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-10-3"><li class="nav-item"><a class="nav-link" href="/cookbook/lists/basic-list"><div><span>Create and use lists</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/horizontal-list"><div><span>Create a horizontal list</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/grid-lists"><div><span>Create a grid view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/mixed-list"><div><span>Create lists with different types of items</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/spaced-items"><div><span>Create lists with spaced items</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/long-lists"><div><span>Work with long lists</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-10-4" role="button" aria-expanded="false" aria-controls="sidenav-10-4"><span>Scrolling</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-10-4"><li class="nav-item"><a class="nav-link" href="/ui/layout/scrolling"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/layout/scrolling/slivers"><div><span>Use slivers to achieve fancy scrolling</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/lists/floating-app-bar"><div><span>Place a floating app bar above a list</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/effects/parallax-scrolling"><div><span>Create a scrolling parallax effect</span></div></a></li></ul></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-11" role="button" aria-expanded="false" aria-controls="sidenav-11"><span>Adaptive & responsive design</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-11"><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/general"><div><span>General approach</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/safearea-mediaquery"><div><span>SafeArea & MediaQuery</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/large-screens"><div><span>Large screens & foldables</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/input"><div><span>User input & accessibility</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/capabilities"><div><span>Capabilities & policies</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/platform-adaptations"><div><span>Automatic platform adaptations</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/best-practices"><div><span>Best practices</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/adaptive-responsive/more-info"><div><span>Additional resources</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-12" role="button" aria-expanded="false" aria-controls="sidenav-12"><span>Design & theming</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-12"><li class="nav-item"><a class="nav-link" href="/cookbook/design/themes"><div><span>Share styles with themes</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/design/material"><div><span>Material design</span></div></a></li><li class="nav-item"><a class="nav-link" href="/release/breaking-changes/material-3-migration"><div><span>Migrate to Material 3</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-12-4" role="button" aria-expanded="false" aria-controls="sidenav-12-4"><span>Text</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-12-4"><li class="nav-item"><a class="nav-link" href="/ui/design/text/typography"><div><span>Fonts & typography</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/fonts"><div><span>Use a custom font</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/package-fonts"><div><span>Export fonts from a package</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/packages/google_fonts" target="_blank" rel="noopener"><div><span>Google Fonts package</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-12-5" role="button" aria-expanded="false" aria-controls="sidenav-12-5"><span>Custom graphics</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-12-5"><li class="nav-item"><a class="nav-link" href="/ui/design/graphics/fragment-shaders"><div><span>Use custom fragment shaders</span></div></a></li></ul></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-13" role="button" aria-expanded="false" aria-controls="sidenav-13"><span>Interactivity</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-13"><li class="nav-item"><a class="nav-link" href="/ui/interactivity"><div><span>Add interactivity to your app</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-13-2" role="button" aria-expanded="false" aria-controls="sidenav-13-2"><span>Gestures</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-13-2"><li class="nav-item"><a class="nav-link" href="/ui/interactivity/gestures"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/gestures/handling-taps"><div><span>Handle taps</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/interactivity/gestures/drag-outside"><div><span>Drag an object outside an app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/effects/drag-a-widget"><div><span>Drag a UI element within an app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/gestures/ripples"><div><span>Add Material touch ripples</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/gestures/dismissible"><div><span>Implement swipe to dismiss</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-13-3" role="button" aria-expanded="false" aria-controls="sidenav-13-3"><span>Input & forms</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-13-3"><li class="nav-item"><a class="nav-link" href="/cookbook/forms/text-input"><div><span>Create and style a text field</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/forms/retrieve-input"><div><span>Retrieve the value of a text field</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/forms/text-field-changes"><div><span>Handle changes to a text field</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/forms/focus"><div><span>Manage focus in text fields</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/forms/validation"><div><span>Build a form with validation</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/snackbars"><div><span>Display a snackbar</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/interactivity/actions-and-shortcuts"><div><span>Implement actions & shortcuts</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/interactivity/focus"><div><span>Manage keyboard focus</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-14" role="button" aria-expanded="false" aria-controls="sidenav-14"><span>Assets & media</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-14"><li class="nav-item"><a class="nav-link" href="/ui/assets/assets-and-images"><div><span>Add assets and images</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/images/network-image"><div><span>Display images from the internet</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/images/fading-in-images"><div><span>Fade in images with a placeholder</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/plugins/play-video"><div><span>Play and pause a video</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/assets/asset-transformation"><div><span>Transform assets at build time</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-15" role="button" aria-expanded="false" aria-controls="sidenav-15"><span>Navigation & routing</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-15"><li class="nav-item"><a class="nav-link" href="/ui/navigation"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/tabs"><div><span>Add tabs to your app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/navigation-basics"><div><span>Navigate to a new screen and back</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/passing-data"><div><span>Send data to a new screen</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/returning-data"><div><span>Return data from a screen</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/design/drawer"><div><span>Add a drawer to a screen</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/navigation/deep-linking"><div><span>Set up deep linking</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/set-up-app-links"><div><span>Set up app links for Android</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/navigation/set-up-universal-links"><div><span>Set up universal links for iOS</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/navigation/url-strategies"><div><span>Configure web URL strategies</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-16" role="button" aria-expanded="false" aria-controls="sidenav-16"><span>Animations & transitions</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-16"><li class="nav-item"><a class="nav-link" href="/ui/animations"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/tutorial"><div><span>Tutorial</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/implicit-animations"><div><span>Implicit animations</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/animation/animated-container"><div><span>Animate the properties of a container</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/animation/opacity-animation"><div><span>Fade a widget in and out</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/hero-animations"><div><span>Hero animations</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/animation/page-route-animation"><div><span>Animate a page route transition</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/animation/physics-simulation"><div><span>Animate using a physics simulation</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/staggered-animations"><div><span>Staggered animations</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/effects/staggered-menu-animation"><div><span>Create a staggered menu animation</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/animations/overview"><div><span>API overview</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-17" role="button" aria-expanded="false" aria-controls="sidenav-17"><span>Accessibility & internationalization</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-17"><li class="nav-item"><a class="nav-link" href="/ui/accessibility-and-internationalization/accessibility"><div><span>Accessibility</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/accessibility-and-internationalization/internationalization"><div><span>Internationalization</span></div></a></li></ul></li><li aria-hidden="true"><div class="sidenav-divider"></div></li><li class="nav-header">Beyond UI</li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-20" role="button" aria-expanded="false" aria-controls="sidenav-20"><span>Data & backend</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-20"><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-20-1" role="button" aria-expanded="false" aria-controls="sidenav-20-1"><span>State management</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-20-1"><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/intro"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/declarative"><div><span>Think declaratively</span></div></a></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/ephemeral-vs-app"><div><span>Ephemeral vs app state</span></div></a></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/simple"><div><span>Simple app state management</span></div></a></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/state-mgmt/options"><div><span>Options</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-20-2" role="button" aria-expanded="false" aria-controls="sidenav-20-2"><span>Networking & http</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-20-2"><li class="nav-item"><a class="nav-link" href="/data-and-backend/networking"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/fetch-data"><div><span>Fetch data from the internet</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/authenticated-requests"><div><span>Make authenticated requests</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/send-data"><div><span>Send data to the internet</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/update-data"><div><span>Update data over the internet</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/delete-data"><div><span>Delete data on the internet</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/web-sockets"><div><span>Communicate with WebSockets</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-20-3" role="button" aria-expanded="false" aria-controls="sidenav-20-3"><span>Serialization</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-20-3"><li class="nav-item"><a class="nav-link" href="/data-and-backend/serialization/json"><div><span>JSON serialization</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/networking/background-parsing"><div><span>Parse JSON in the background</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-20-4" role="button" aria-expanded="false" aria-controls="sidenav-20-4"><span>Persistence</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-20-4"><li class="nav-item"><a class="nav-link" href="/cookbook/persistence/key-value"><div><span>Store key-value data on disk</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/persistence/reading-writing-files"><div><span>Read and write files</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/persistence/sqlite"><div><span>Persist data with SQLite</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-20-5" role="button" aria-expanded="false" aria-controls="sidenav-20-5"><span>Firebase</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-20-5"><li class="nav-item"><a class="nav-link" href="/data-and-backend/firebase"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://firebase.google.com/docs/flutter/setup" target="_blank" rel="noopener"><div><span>Add Firebase to your Flutter app</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="/data-and-backend/google-apis"><div><span>Google APIs</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-21" role="button" aria-expanded="false" aria-controls="sidenav-21"><span>App architecture</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-21"><li class="nav-item"><a class="nav-link" href="/app-architecture"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/concepts"><div><span>Architecture concepts</span></div></a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/guide"><div><span>Guide to app architecture</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-21-4" role="button" aria-expanded="false" aria-controls="sidenav-21-4"><span>Architecture case study</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-21-4"><li class="nav-item"><a class="nav-link" href="/app-architecture/case-study"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/case-study/ui-layer"><div><span>UI layer</span></div></a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/case-study/data-layer"><div><span>Data layer</span></div></a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/case-study/dependency-injection"><div><span>Dependency injection</span></div></a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/case-study/testing"><div><span>Testing each layer</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="/app-architecture/recommendations"><div><span>Recommendations</span></div></a></li><li class="nav-item"><a class="nav-link" href="/app-architecture/design-patterns"><div><span>Design patterns</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-22" role="button" aria-expanded="false" aria-controls="sidenav-22"><span>Platform integration</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-22"><li class="nav-item"><a class="nav-link" href="/reference/supported-platforms"><div><span>Supported platforms</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/desktop"><div><span>Build desktop apps with Flutter</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/platform-channels"><div><span>Write platform-specific code</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-22-4" role="button" aria-expanded="false" aria-controls="sidenav-22-4"><span>Android</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-22-4"><li class="nav-item"><a class="nav-link" href="/platform-integration/android/install-android"><div><span>Add Android as build target</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/splash-screen"><div><span>Add a splash screen</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/predictive-back"><div><span>Add predictive back</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/c-interop"><div><span>Bind to native code</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/platform-views"><div><span>Host a native Android view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/call-jetpack-apis"><div><span>Calling JetPack APIs</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/compose-activity"><div><span>Launch a Jetpack Compose activity</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/restore-state-android"><div><span>Restore state on Android</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/android/chromeos"><div><span>Target ChromeOS with Android</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-22-5" role="button" aria-expanded="false" aria-controls="sidenav-22-5"><span>iOS</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-22-5"><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/install-ios"><div><span>Add iOS as build target</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/ios-latest"><div><span>Flutter on latest iOS</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/apple-frameworks"><div><span>Leverage Apple's system libraries</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/launch-screen"><div><span>Add a launch screen</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/ios-app-clip"><div><span>Add iOS App Clip support</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/app-extensions"><div><span>Add iOS app extensions</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/c-interop"><div><span>Bind to native code</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/platform-views"><div><span>Host a native iOS view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/ios-debugging"><div><span>Enable debugging on iOS</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/ios/restore-state-ios"><div><span>Restore state on iOS</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-22-6" role="button" aria-expanded="false" aria-controls="sidenav-22-6"><span>Linux</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-22-6"><li class="nav-item"><a class="nav-link" href="/platform-integration/linux/install-linux"><div><span>Add Linux as build target</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/linux/building"><div><span>Build a Linux app</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-22-7" role="button" aria-expanded="false" aria-controls="sidenav-22-7"><span>macOS</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-22-7"><li class="nav-item"><a class="nav-link" href="/platform-integration/macos/install-macos"><div><span>Add macOS as build target</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/macos/building"><div><span>Build a macOS app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/macos/c-interop"><div><span>Bind to native code</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/macos/platform-views"><div><span>Host a native macOS view</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-22-8" role="button" aria-expanded="false" aria-controls="sidenav-22-8"><span>Web</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-22-8"><li class="nav-item"><a class="nav-link" href="/platform-integration/web"><div><span>Web support in Flutter</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/install-web"><div><span>Add web as build target</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/building"><div><span>Build a web app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/wasm"><div><span>Compile to WebAssembly</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/initialization"><div><span>Customize app initialization</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/embedding-flutter-web"><div><span>Add Flutter to any web app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/web-content-in-flutter"><div><span>Web content in Flutter</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/renderers"><div><span>Web renderers</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/web-images"><div><span>Display images on the web</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/faq"><div><span>Web FAQ</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-22-9" role="button" aria-expanded="false" aria-controls="sidenav-22-9"><span>Windows</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-22-9"><li class="nav-item"><a class="nav-link" href="/platform-integration/windows/install-windows"><div><span>Add Windows as build target</span></div></a></li><li class="nav-item"><a class="nav-link" href="/platform-integration/windows/building"><div><span>Build a Windows app</span></div></a></li></ul></li></ul></li><li class="nav-item"><button class="nav-link active collapsible" data-toggle="collapse" data-target="#sidenav-23" role="button" aria-expanded="true" aria-controls="sidenav-23"><span>Packages & plugins</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse show" id="sidenav-23"><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/using-packages"><div><span>Use packages & plugins</span></div></a></li><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/developing-packages"><div><span>Develop packages & plugins</span></div></a></li><li class="nav-item"><button class="nav-link active collapsible" data-toggle="collapse" data-target="#sidenav-23-3" role="button" aria-expanded="true" aria-controls="sidenav-23-3"><span>Swift Package Manager</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse show" id="sidenav-23-3"><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/swift-package-manager/for-app-developers"><div><span>For app developers</span></div></a></li><li class="nav-item"><a class="nav-link active" href="/packages-and-plugins/swift-package-manager/for-plugin-authors"><div><span>For plugin authors</span></div></a></li></ul></li><div class="sidenav-divider"></div><li class="nav-item"><a class="nav-link" href="/packages-and-plugins/favorites"><div><span>Flutter Favorites</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://pub.dev/flutter" target="_blank" rel="noopener"><div><span>Package repository</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-24" role="button" aria-expanded="false" aria-controls="sidenav-24"><span>Testing & debugging</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-24"><li class="nav-header">Testing</li><li class="nav-item"><a class="nav-link" href="/testing/overview"><div><span>Overview</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-24-3" role="button" aria-expanded="false" aria-controls="sidenav-24-3"><span>Unit testing</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-24-3"><li class="nav-item"><a class="nav-link" href="/cookbook/testing/unit/introduction"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/unit/mocking"><div><span>Mock dependencies</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-24-4" role="button" aria-expanded="false" aria-controls="sidenav-24-4"><span>Widget testing</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-24-4"><li class="nav-item"><a class="nav-link" href="/cookbook/testing/widget/introduction"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/widget/finders"><div><span>Find widgets</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/widget/scrolling"><div><span>Simulate scrolling</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/widget/tap-drag"><div><span>Simulate user interaction</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-24-5" role="button" aria-expanded="false" aria-controls="sidenav-24-5"><span>Integration testing</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-24-5"><li class="nav-item"><a class="nav-link" href="/cookbook/testing/integration/introduction"><div><span>Introduction</span></div></a></li><li class="nav-item"><a class="nav-link" href="/testing/integration-tests"><div><span>Write and run an integration test</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/testing/integration/profiling"><div><span>Profile an integration test</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="/testing/testing-plugins"><div><span>Test a plugin</span></div></a></li><li class="nav-item"><a class="nav-link" href="/testing/plugins-in-tests"><div><span>Handle plugin code in tests</span></div></a></li><li class="nav-header">Debugging</li><li class="nav-item"><a class="nav-link" href="/testing/debugging"><div><span>Debugging tools</span></div></a></li><li class="nav-item"><a class="nav-link" href="/testing/code-debugging"><div><span>Debug your app programmatically</span></div></a></li><li class="nav-item"><a class="nav-link" href="/testing/native-debugging"><div><span>Use a native language debugger</span></div></a></li><li class="nav-item"><a class="nav-link" href="/testing/common-errors"><div><span>Common Flutter errors</span></div></a></li><li class="nav-item"><a class="nav-link" href="/testing/errors"><div><span>Handle errors</span></div></a></li><li class="nav-item"><a class="nav-link" href="/cookbook/maintenance/error-reporting"><div><span>Report errors to a service</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-25" role="button" aria-expanded="false" aria-controls="sidenav-25"><span>Performance & optimization</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-25"><li class="nav-item"><a class="nav-link" href="/perf"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/impeller"><div><span>Impeller</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/best-practices"><div><span>Performance best practices</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/app-size"><div><span>App size</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/deferred-components"><div><span>Deferred components</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/rendering-performance"><div><span>Rendering performance</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/ui-performance"><div><span>Performance profiling</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/web-performance"><div><span>Performance profiling for web</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/metrics"><div><span>Performance metrics</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/isolates"><div><span>Concurrency and isolates</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/faq"><div><span>Performance FAQ</span></div></a></li><li class="nav-item"><a class="nav-link" href="/perf/appendix"><div><span>Appendix</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-26" role="button" aria-expanded="false" aria-controls="sidenav-26"><span>Deployment</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-26"><li class="nav-item"><a class="nav-link" href="/deployment/obfuscate"><div><span>Obfuscate Dart code</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/flavors"><div><span>Create app flavors for Android</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/flavors-ios"><div><span>Create app flavors for iOS and macOS</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/android"><div><span>Build and release an Android app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/ios"><div><span>Build and release an iOS app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/macos"><div><span>Build and release a macOS app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/linux"><div><span>Build and release a Linux app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/windows"><div><span>Build and release a Windows app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/web"><div><span>Build and release a web app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/deployment/cd"><div><span>Set up continuous deployment</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-27" role="button" aria-expanded="false" aria-controls="sidenav-27"><span>Add to an existing app</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-27"><li class="nav-item"><a class="nav-link" href="/add-to-app"><div><span>Introduction</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-27-2" role="button" aria-expanded="false" aria-controls="sidenav-27-2"><span>Add to an Android app</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-27-2"><li class="nav-item"><a class="nav-link" href="/add-to-app/android/project-setup"><div><span>Set up Android project</span></div></a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/android/add-flutter-screen"><div><span>Add a single Flutter screen</span></div></a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/android/add-flutter-fragment"><div><span>Add a Flutter Fragment</span></div></a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/android/add-flutter-view"><div><span>Add a Flutter View</span></div></a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/android/plugin-setup"><div><span>Use a Flutter plugin</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-27-3" role="button" aria-expanded="false" aria-controls="sidenav-27-3"><span>Add to an iOS app</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-27-3"><li class="nav-item"><a class="nav-link" href="/add-to-app/ios/project-setup"><div><span>Set up iOS project</span></div></a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/ios/add-flutter-screen"><div><span>Add a single Flutter screen</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="/platform-integration/web/embedding-flutter-web"><div><span>Add to a web app</span></div></a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/debugging"><div><span>Debug embedded Flutter module</span></div></a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/multiple-flutters"><div><span>Add multiple Flutter instances</span></div></a></li><li class="nav-item"><a class="nav-link" href="/add-to-app/performance"><div><span>Loading sequence and performance</span></div></a></li></ul></li><li aria-hidden="true"><div class="sidenav-divider"></div></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-29" role="button" aria-expanded="false" aria-controls="sidenav-29"><span>Tools & editors</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-29"><li class="nav-item"><a class="nav-link" href="/tools/android-studio"><div><span>Android Studio & IntelliJ</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/vs-code"><div><span>Visual Studio Code</span></div></a></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-29-3" role="button" aria-expanded="false" aria-controls="sidenav-29-3"><span>DevTools</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-29-3"><li class="nav-item"><a class="nav-link" href="/tools/devtools"><div><span>Overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/android-studio"><div><span>Run from Android Studio & IntelliJ</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/vscode"><div><span>Run from VS Code</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/cli"><div><span>Run from command line</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/inspector"><div><span>Flutter inspector</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/legacy-inspector"><div><span>Legacy Flutter inspector</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/performance"><div><span>Performance view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/cpu-profiler"><div><span>CPU Profiler view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/memory"><div><span>Memory view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/console"><div><span>Debug console view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/network"><div><span>Network view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/debugger"><div><span>Debugger</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/logging"><div><span>Logging view</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/app-size"><div><span>App size tool</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/extensions"><div><span>DevTools extensions</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/deep-links"><div><span>Validate deep links</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/devtools/release-notes"><div><span>Release notes</span></div></a></li></ul></li><li class="nav-item"><a class="nav-link" href="/tools/sdk"><div><span>SDK overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/pubspec"><div><span>Flutter's pubspec options</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/flutter-fix"><div><span>Automated fixes</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/formatting"><div><span>Code formatting</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-30" role="button" aria-expanded="false" aria-controls="sidenav-30"><span>Flutter concepts</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-30"><li class="nav-item"><a class="nav-link" href="/resources/architectural-overview"><div><span>Architectural overview</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/inside-flutter"><div><span>Inside Flutter</span></div></a></li><li class="nav-item"><a class="nav-link" href="/ui/layout/constraints"><div><span>Understanding constraints</span></div></a></li><li class="nav-item"><a class="nav-link" href="/testing/build-modes"><div><span>Flutter's build modes</span></div></a></li><li class="nav-item"><a class="nav-link" href="/tools/hot-reload"><div><span>Hot reload</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsed collapsible" data-toggle="collapse" data-target="#sidenav-31" role="button" aria-expanded="false" aria-controls="sidenav-31"><span>Resources</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-31"><li class="nav-item"><a class="nav-link" href="/resources/faq"><div><span>FAQ</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/books"><div><span>Books</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/videos"><div><span>Videos</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/courses"><div><span>Courses</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/bootstrap-into-dart"><div><span>Learn Dart</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/support"><div><span>Get support</span></div></a></li><div class="sidenav-divider"></div><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-31-8" role="button" aria-expanded="false" aria-controls="sidenav-31-8"><span>Contribute</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-31-8"><li class="nav-item"><a class="nav-link" href="/resources/bug-reports"><div><span>Create useful bug reports</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://github.com/flutter/flutter/blob/main/CONTRIBUTING.md" target="_blank" rel="noopener"><div><span>Contribute to Flutter</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li><li class="nav-item"><a class="nav-link" href="/resources/design-docs"><div><span>Discover proposed features</span></div></a></li></ul></li><li class="nav-item"><button class="nav-link collapsible collapsed" data-toggle="collapse" data-target="#sidenav-31-9" role="button" aria-expanded="false" aria-controls="sidenav-31-9"><span>Reference</span> <span class="material-symbols expander" aria-hidden="true">expand_more</span></button><ul class="nav collapse" id="sidenav-31-9"><li class="nav-item"><a class="nav-link" href="/dash"><div><span>Who is Dash?</span></div></a></li><li class="nav-item"><a class="nav-link" href="/reference/widgets"><div><span>Widget index</span></div></a></li><li class="nav-item"><a class="nav-link" href="/reference/flutter-cli"><div><span>flutter CLI</span></div></a></li><li class="nav-item"><a class="nav-link" href="https://api.flutter.dev" target="_blank" rel="noopener"><div><span>API docs</span><span class="material-symbols" aria-hidden="true">open_in_new</span></div></a></li></ul></li></ul></li></ul></nav></div><main class="site-content"><div id="site-toc--side" class="site-toc"><header class="site-toc__title">Contents</header><ul class="section-nav"><li class="toc-entry nav-item"><a class="nav-link" href="#how-to-turn-on-swift-package-manager">How to turn on Swift Package Manager</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#how-to-turn-off-swift-package-manager">How to turn off Swift Package Manager</a><ul class="nav"><li class="toc-entry nav-item"><a class="nav-link" href="#turn-off-for-a-single-project">Turn off for a single project</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#turn-off-globally-for-all-projects">Turn off globally for all projects</a></li></ul></li><li class="toc-entry nav-item"><a class="nav-link" href="#how-to-add-swift-package-manager-support-to-an-existing-flutter-plugin">How to add Swift Package Manager support to an existing Flutter plugin</a></li><li class="toc-entry nav-item"><a class="nav-link" href="#how-to-update-unit-tests-in-a-plugins-example-app">How to update unit tests in a plugin's example app</a></li></ul></div><article><header class="site-content__title"><h1 id="document-title">Swift Package Manager for plugin authors</h1><nav class="breadcrumbs" aria-label="breadcrumb"><ol vocab="https://schema.org/" typeof="BreadcrumbList"><li class="breadcrumb-item" property="itemListElement" typeof="ListItem"><a href="/packages-and-plugins" property="item" typeof="WebPage"><span property="name">Packages & plugins</span></a><meta property="position" content="0"><span class="material-symbols child-icon" aria-hidden="true">chevron_right</span></li><li class="breadcrumb-item" property="itemListElement" typeof="ListItem"><a href="/packages-and-plugins/swift-package-manager" property="item" typeof="WebPage"><span property="name">Swift Package Manager for Flutter</span></a><meta property="position" content="1"><span class="material-symbols child-icon" aria-hidden="true">chevron_right</span></li><li class="breadcrumb-item active" property="itemListElement" typeof="ListItem" aria-current="page"><a href="/packages-and-plugins/swift-package-manager/for-plugin-authors" property="item" typeof="WebPage"><span property="name">Swift Package Manager for plugin authors</span></a><meta property="position" content="2"></li></ol></nav></header><div id="site-toc--inline" class="site-toc"><header class="site-toc__title">Contents</header><ul class="section-nav"><li class="toc-entry"><a href="#how-to-turn-on-swift-package-manager">How to turn on Swift Package Manager</a></li><li class="toc-entry"><a href="#how-to-turn-off-swift-package-manager">How to turn off Swift Package Manager</a><ul><li class="toc-entry"><a href="#turn-off-for-a-single-project">Turn off for a single project</a></li><li class="toc-entry"><a href="#turn-off-globally-for-all-projects">Turn off globally for all projects</a></li></ul></li><li class="toc-entry"><a href="#how-to-add-swift-package-manager-support-to-an-existing-flutter-plugin">How to add Swift Package Manager support to an existing Flutter plugin</a></li><li class="toc-entry"><a href="#how-to-update-unit-tests-in-a-plugins-example-app">How to update unit tests in a plugin's example app</a></li></ul></div><aside class="alert alert-warning"><div class="alert-header"><i class="material-symbols" aria-hidden="true">warning</i> <span>Warning</span></div><div class="alert-content"><p>Flutter is migrating to <a href="https://www.swift.org/documentation/package-manager/">Swift Package Manager</a> to manage iOS and macOS native dependencies. Flutter's support of Swift Package Manager is under development. If you find a bug in Flutter's Swift Package Manager support, <a href="https://github.com/flutter/flutter/issues/new?template=2_bug.yml">open an issue</a>. Swift Package Manager support is <a href="#how-to-turn-on-swift-package-manager">off by default</a>. Flutter continues to support CocoaPods.</p></div></aside><p>Flutter's Swift Package Manager integration has several benefits:</p><ol><li><strong>Provides access to the Swift package ecosystem</strong>. Flutter plugins can use the growing ecosystem of <a href="https://swiftpackageindex.com/">Swift packages</a>!</li><li><strong>Simplifies Flutter installation</strong>. Swift Package Manager is bundled with Xcode. In the future, you won’t need to install Ruby and CocoaPods to target iOS or macOS.</li></ol><div class="header-wrapper"><h2 id="how-to-turn-on-swift-package-manager">How to turn on Swift Package Manager</h2><a class="heading-link" href="#how-to-turn-on-swift-package-manager" aria-label="Link to 'How to turn on Swift Package Manager' section">#</a></div><p>Flutter's Swift Package Manager support is turned off by default. To turn it on:</p><ol><li><p>Upgrade to the latest Flutter SDK:</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">flutter</span><span style="color:#0C7064"> upgrade</span></span></code></pre></div></div></li><li><p>Turn on the Swift Package Manager feature:</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">flutter</span><span style="color:#0C7064"> config</span><span style="color:#0C7064"> --enable-swift-package-manager</span></span></code></pre></div></div></li></ol><p>Using the Flutter CLI to run an app <a href="/packages-and-plugins/swift-package-manager/for-app-developers/#how-to-add-swift-package-manager-integration">migrates the project</a> to add Swift Package Manager integration. This makes your project download the Swift packages that your Flutter plugins depend on. An app with Swift Package Manager integration requires Flutter version 3.24 or higher. To use an older Flutter version, you will need to <a href="/packages-and-plugins/swift-package-manager/for-app-developers#how-to-remove-swift-package-manager-integration">remove Swift Package Manager integration</a> from the app.</p><p>Flutter falls back to CocoaPods for dependencies that do not support Swift Package Manager yet.</p><div class="header-wrapper"><h2 id="how-to-turn-off-swift-package-manager">How to turn off Swift Package Manager</h2><a class="heading-link" href="#how-to-turn-off-swift-package-manager" aria-label="Link to 'How to turn off Swift Package Manager' section">#</a></div><aside class="alert alert-secondary"><div class="alert-header"><span>Plugin authors</span></div><div class="alert-content"><p>Plugin authors need to turn on and off Flutter's Swift Package Manager support for testing. App developers do not need to disable Swift Package Manager support, unless they are running into issues.</p><p>If you find a bug in Flutter's Swift Package Manager support, <a href="https://github.com/flutter/flutter/issues/new?template=2_bug.yml">open an issue</a>.</p></div></aside><p>Disabling Swift Package Manager causes Flutter to use CocoaPods for all dependencies. However, Swift Package Manager remains integrated with your project. To remove Swift Package Manager integration completely from your project, follow the <a href="/packages-and-plugins/swift-package-manager/for-app-developers#how-to-remove-swift-package-manager-integration">How to remove Swift Package Manager integration</a> instructions.</p><div class="header-wrapper"><h3 id="turn-off-for-a-single-project">Turn off for a single project</h3><a class="heading-link" href="#turn-off-for-a-single-project" aria-label="Link to 'Turn off for a single project' section">#</a></div><p>In the project's <code>pubspec.yaml</code> file, under the <code>flutter</code> section, add <code>disable-swift-package-manager: true</code>.</p><div class="code-block-wrapper language-yaml"><div class="code-block-header">pubspec.yaml</div><div class="code-block-body"><span class="code-block-language" title="Language yaml">yaml</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6E6E70"># The following section is specific to Flutter packages.</span></span> <span class="line"><span style="color:#0468D7">flutter</span><span style="color:#222222">:</span></span> <span class="line"><span style="color:#0468D7"> disable-swift-package-manager</span><span style="color:#222222">: </span><span style="color:#0C7064">true</span></span></code></pre></div></div><p>This turns off Swift Package Manager for all contributors to this project.</p><div class="header-wrapper"><h3 id="turn-off-globally-for-all-projects">Turn off globally for all projects</h3><a class="heading-link" href="#turn-off-globally-for-all-projects" aria-label="Link to 'Turn off globally for all projects' section">#</a></div><p>Run the following command:</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">flutter</span><span style="color:#0C7064"> config</span><span style="color:#0C7064"> --no-enable-swift-package-manager</span></span></code></pre></div></div><p>This turns off Swift Package Manager for the current user.</p><p>If a project is incompatible with Swift Package Manager, all contributors need to run this command.</p><div class="header-wrapper"><h2 id="how-to-add-swift-package-manager-support-to-an-existing-flutter-plugin">How to add Swift Package Manager support to an existing Flutter plugin</h2><a class="heading-link" href="#how-to-add-swift-package-manager-support-to-an-existing-flutter-plugin" aria-label="Link to 'How to add Swift Package Manager support to an existing Flutter plugin' section">#</a></div><p>This guide shows how to add Swift Package Manager support to a plugin that already supports CocoaPods. This ensures the plugin is usable by all Flutter projects.</p><p>Flutter plugins should support <em>both</em> Swift Package Manager and CocoaPods until further notice.</p><p>Swift Package Manager adoption will be gradual. Plugins that don't support CocoaPods won't be usable by projects that haven't migrated to Swift Package Manager yet. Plugins that don't support Swift Package Manager can cause problems for projects that have migrated.</p><div class="tabs-wrapper"><ul class="nav nav-tabs" role="tablist"><li class="nav-item"><a class="nav-link active" data-tab-save-id="swift-plugin" id="113-tab" href="#113-tab-panel" role="tab" aria-controls="113-tab-panel" aria-selected="true">Swift plugin</a></li><li class="nav-item"><a class="nav-link" data-tab-save-id="objective-c-plugin" id="114-tab" href="#114-tab-panel" role="tab" aria-controls="114-tab-panel" aria-selected="false">Objective-C plugin</a></li></ul><div class="tab-content"><div class="tab-pane active" id="113-tab-panel" role="tabpanel" aria-labelledby="113-tab"><p>Replace <code>plugin_name</code> throughout this guide with the name of your plugin. The example below uses <code>ios</code>, replace <code>ios</code> with <code>macos</code>/<code>darwin</code> as applicable.</p><ol><li><p><a href="/packages-and-plugins/swift-package-manager/for-plugin-authors#how-to-turn-on-swift-package-manager">Turn on the Swift Package Manager feature</a>.</p></li><li><p>Start by creating a directory under the <code>ios</code>, <code>macos</code>, and/or <code>darwin</code> directories. Name this new directory the name of the platform package.</p><pre> plugin_name/ios/ ├── ... └── <b>plugin_name/</b> </pre></li><li><p>Within this new directory, create the following files/directories:</p><ul><li><code>Package.swift</code> (file)</li><li><code>Sources</code> (directory)</li><li><code>Sources/plugin_name</code> (directory)</li></ul><p>Your plugin should look like:</p><pre> plugin_name/ios/ ├── ... └── plugin_name/ ├── <b>Package.swift</b> └── <b>Sources/plugin_name/</b> </pre></li><li><p>Use the following template in the <code>Package.swift</code> file:</p><div class="code-block-wrapper language-swift"><div class="code-block-header">Package.swift</div><div class="code-block-body"><span class="code-block-language" title="Language swift">swift</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6E6E70">// swift-tools-version: 5.9</span></span> <span class="line"><span style="color:#6E6E70">// The swift-tools-version declares the minimum version of Swift required to build this package.</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">import</span><span style="color:#0468D7"> PackageDescription</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">let</span><span style="color:#BD2314"> package</span><span style="color:#222222"> = </span><span style="color:#6200EE">Package</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update your plugin name.</span></span> <span class="line"><span style="color:#6200EE"> name</span><span style="color:#222222">: </span><span style="color:#0C7064">"plugin_name"</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#6200EE"> platforms</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update the platforms your plugin supports.</span></span> <span class="line"><span style="color:#6E6E70"> // If your plugin only supports iOS, remove `.macOS(...)`.</span></span> <span class="line"><span style="color:#6E6E70"> // If your plugin only supports macOS, remove `.iOS(...)`.</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">iOS</span><span style="color:#222222">(</span><span style="color:#0C7064">"12.0"</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">macOS</span><span style="color:#222222">(</span><span style="color:#0C7064">"10.14"</span><span style="color:#222222">)</span></span> <span class="line"><span style="color:#222222"> ],</span></span> <span class="line"><span style="color:#6200EE"> products</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update your library and target names.</span></span> <span class="line"><span style="color:#6E6E70"> // If the plugin name contains "_", replace with "-" for the library name.</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">library</span><span style="color:#222222">(</span><span style="color:#6200EE">name</span><span style="color:#222222">: </span><span style="color:#0C7064">"plugin-name"</span><span style="color:#222222">, </span><span style="color:#6200EE">targets</span><span style="color:#222222">: [</span><span style="color:#0C7064">"plugin_name"</span><span style="color:#222222">])</span></span> <span class="line"><span style="color:#222222"> ],</span></span> <span class="line"><span style="color:#6200EE"> dependencies</span><span style="color:#222222">: [],</span></span> <span class="line"><span style="color:#6200EE"> targets</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">target</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update your target name.</span></span> <span class="line"><span style="color:#6200EE"> name</span><span style="color:#222222">: </span><span style="color:#0C7064">"plugin_name"</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#6200EE"> dependencies</span><span style="color:#222222">: [],</span></span> <span class="line"><span style="color:#6200EE"> resources</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: If your plugin requires a privacy manifest</span></span> <span class="line"><span style="color:#6E6E70"> // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file</span></span> <span class="line"><span style="color:#6E6E70"> // to describe your plugin's privacy impact, and then uncomment this line.</span></span> <span class="line"><span style="color:#6E6E70"> // For more information, see:</span></span> <span class="line"><span style="color:#6E6E70"> // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files</span></span> <span class="line"><span style="color:#6E6E70"> // .process("PrivacyInfo.xcprivacy"),</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70"> // TODO: If you have other resources that need to be bundled with your plugin, refer to</span></span> <span class="line"><span style="color:#6E6E70"> // the following instructions to add them:</span></span> <span class="line"><span style="color:#6E6E70"> // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package</span></span> <span class="line"><span style="color:#222222"> ]</span></span> <span class="line"><span style="color:#222222"> )</span></span> <span class="line"><span style="color:#222222"> ]</span></span> <span class="line"><span style="color:#222222">)</span></span></code></pre></div></div></li><li><p>Update the <a href="https://developer.apple.com/documentation/packagedescription/supportedplatform">supported platforms</a> in your <code>Package.swift</code> file.</p><div class="code-block-wrapper language-swift"><div class="code-block-header">Package.swift</div><div class="code-block-body"><span class="code-block-language" title="Language swift">swift</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222"> platforms: [</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update the platforms your plugin supports.</span></span> <span class="line"><span style="color:#6E6E70"> // If your plugin only supports iOS, remove `.macOS(...)`.</span></span> <span class="line"><span style="color:#6E6E70"> // If your plugin only supports macOS, remove `.iOS(...)`.</span></span> <span class="line"><span style="color:#222222"> </span><mark class="highlight"><span style="color:#222222">.</span><span style="color:#6200EE">iOS</span><span style="color:#222222">(</span><span style="color:#0C7064">"12.0"</span><span style="color:#222222">),</span></mark></span> <span class="line"><span style="color:#222222"> </span><mark class="highlight"><span style="color:#222222">.</span><span style="color:#6200EE">macOS</span><span style="color:#222222">(</span><span style="color:#0C7064">"10.14"</span><span style="color:#222222">)</span></mark></span> <span class="line"><span style="color:#222222"> ],</span></span></code></pre></div></div></li><li><p>Update the package, library, and target names in your <code>Package.swift</code> file.</p><div class="code-block-wrapper language-swift"><div class="code-block-header">Package.swift</div><div class="code-block-body"><span class="code-block-language" title="Language swift">swift</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#BD2314">let</span><span style="color:#BD2314"> package</span><span style="color:#222222"> = </span><span style="color:#6200EE">Package</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update your plugin name.</span></span> <span class="line"><span style="color:#6200EE"> name</span><span style="color:#222222">: </span><mark class="highlight"><span style="color:#0C7064">"plugin_name"</span></mark><span style="color:#222222">,</span></span> <span class="line"><span style="color:#6200EE"> platforms</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">iOS</span><span style="color:#222222">(</span><span style="color:#0C7064">"12.0"</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">macOS</span><span style="color:#222222">(</span><span style="color:#0C7064">"10.14"</span><span style="color:#222222">)</span></span> <span class="line"><span style="color:#222222"> ],</span></span> <span class="line"><span style="color:#6200EE"> products</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update your library and target names.</span></span> <span class="line"><span style="color:#6E6E70"> // If the plugin name contains "_", replace with "-" for the library name</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">library</span><span style="color:#222222">(</span><span style="color:#6200EE">name</span><span style="color:#222222">: </span><mark class="highlight"><span style="color:#0C7064">"plugin-name"</span></mark><span style="color:#222222">, </span><span style="color:#6200EE">targets</span><span style="color:#222222">: [</span><mark class="highlight"><span style="color:#0C7064">"plugin_name"</span></mark><span style="color:#222222">])</span></span> <span class="line"><span style="color:#222222"> ],</span></span> <span class="line"><span style="color:#6200EE"> dependencies</span><span style="color:#222222">: [],</span></span> <span class="line"><span style="color:#6200EE"> targets</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">target</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update your target name.</span></span> <span class="line"><span style="color:#6200EE"> name</span><span style="color:#222222">: </span><mark class="highlight"><span style="color:#0C7064">"plugin_name"</span></mark><span style="color:#222222">,</span></span> <span class="line"><span style="color:#6200EE"> dependencies</span><span style="color:#222222">: [],</span></span> <span class="line"><span style="color:#6200EE"> resources</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: If your plugin requires a privacy manifest</span></span> <span class="line"><span style="color:#6E6E70"> // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file</span></span> <span class="line"><span style="color:#6E6E70"> // to describe your plugin's privacy impact, and then uncomment this line.</span></span> <span class="line"><span style="color:#6E6E70"> // For more information, see:</span></span> <span class="line"><span style="color:#6E6E70"> // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files</span></span> <span class="line"><span style="color:#6E6E70"> // .process("PrivacyInfo.xcprivacy"),</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70"> // TODO: If you have other resources that need to be bundled with your plugin, refer to</span></span> <span class="line"><span style="color:#6E6E70"> // the following instructions to add them:</span></span> <span class="line"><span style="color:#6E6E70"> // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package</span></span> <span class="line"><span style="color:#222222"> ]</span></span> <span class="line"><span style="color:#222222"> )</span></span> <span class="line"><span style="color:#222222"> ]</span></span> <span class="line"><span style="color:#222222">)</span></span></code></pre></div></div><aside class="alert alert-info"><div class="alert-header"><i class="material-symbols" aria-hidden="true">info</i> <span>Note</span></div><div class="alert-content"><p>If the plugin name contains <code>_</code>, the library name must be a <code>-</code> separated version of the plugin name.</p></div></aside></li><li><p>If your plugin has a <a href="https://developer.apple.com/documentation/bundleresources/privacy_manifest_files"><code>PrivacyInfo.xcprivacy</code> file</a>, move it to <code>ios/plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacy</code> and uncomment the resource in the <code>Package.swift</code> file.</p><div class="code-block-wrapper language-swift"><div class="code-block-header">Package.swift</div><div class="code-block-body"><span class="code-block-language" title="Language swift">swift</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222"> resources: [</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: If your plugin requires a privacy manifest</span></span> <span class="line"><span style="color:#6E6E70"> // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file</span></span> <span class="line"><span style="color:#6E6E70"> // to describe your plugin's privacy impact, and then uncomment this line.</span></span> <span class="line"><span style="color:#6E6E70"> // For more information, see:</span></span> <span class="line"><span style="color:#6E6E70"> // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files</span></span> <span class="line"><span style="color:#222222"> </span><mark class="highlight"><span style="color:#222222">.</span><span style="color:#6200EE">process</span><span style="color:#222222">(</span><span style="color:#0C7064">"PrivacyInfo.xcprivacy"</span><span style="color:#222222">),</span></mark></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70"> // TODO: If you have other resources that need to be bundled with your plugin, refer to</span></span> <span class="line"><span style="color:#6E6E70"> // the following instructions to add them:</span></span> <span class="line"><span style="color:#6E6E70"> // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package</span></span> <span class="line"><span style="color:#222222"> ],</span></span></code></pre></div></div></li><li><p>Move any resource files from <code>ios/Assets</code> to <code>ios/plugin_name/Sources/plugin_name</code> (or a subdirectory). Add the resource files to your <code>Package.swift</code> file, if applicable. For more instructions, see <a href="https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package">https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package</a>.</p></li><li><p>Move all files from <code>ios/Classes</code> to <code>ios/plugin_name/Sources/plugin_name</code>.</p></li><li><p>The <code>ios/Assets</code>, <code>ios/Resources</code>, and <code>ios/Classes</code> directories should now be empty and can be deleted.</p></li><li><p>If your plugin uses <a href="https://pub.dev/packages/pigeon">Pigeon</a>, update your Pigeon input file.</p><div class="code-block-wrapper language-dart"><div class="code-block-header">pigeons/messages.dart</div><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222">kotlinOptions: </span><span style="color:#0468D7">KotlinOptions</span><span style="color:#222222">(),</span></span> <span class="line"><span style="color:#222222">javaOut: </span><span style="color:#0C7064">'android/app/src/main/java/io/flutter/plugins/Messages.java'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222">javaOptions: </span><span style="color:#0468D7">JavaOptions</span><span style="color:#222222">(),</span></span> <span class="line removed-line"><span style="color:#222222">swiftOut: </span><span style="color:#0C7064">'ios/Classes/messages.g.swift'</span><span style="color:#222222">,</span></span> <span class="line added-line"><span style="color:#222222">swiftOut: </span><span style="color:#0C7064">'ios/plugin_name/Sources/plugin_name/messages.g.swift'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222">swiftOptions: </span><span style="color:#0468D7">SwiftOptions</span><span style="color:#222222">(),</span></span></code></pre></div></div></li><li><p>Update your <code>Package.swift</code> file with any customizations you might need.</p><ol><li><p>Open the <code>ios/plugin_name/</code> directory in Xcode.</p></li><li><p>In Xcode, open your <code>Package.swift</code> file. Verify Xcode doesn't produce any warnings or errors for this file.</p><aside class="alert alert-success"><div class="alert-header"><i class="material-symbols" aria-hidden="true">lightbulb</i> <span>Tip</span></div><div class="alert-content"><p>If Xcode doesn't show any files, quit Xcode (<strong>Xcode > Quit Xcode</strong>) and reopen.</p><p>If Xcode doesn't update after you make a change, try clicking <strong>File > Packages > Reset Package Caches</strong>.</p></div></aside></li><li><p>If your <code>ios/plugin_name.podspec</code> file has <a href="https://guides.cocoapods.org/syntax/podspec.html#dependency">CocoaPods <code>dependency</code></a>s, add the corresponding <a href="https://developer.apple.com/documentation/packagedescription/package/dependency">Swift Package Manager dependencies</a> to your <code>Package.swift</code> file.</p></li><li><p>If your package must be linked explicitly <code>static</code> or <code>dynamic</code> (<a href="https://developer.apple.com/documentation/packagedescription/product/library(name:type:targets:)">not recommended by Apple</a>), update the <a href="https://developer.apple.com/documentation/packagedescription/product">Product</a> to define the type:</p><div class="code-block-wrapper language-swift"><div class="code-block-header">Package.swift</div><div class="code-block-body"><span class="code-block-language" title="Language swift">swift</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222">products: [</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">library</span><span style="color:#222222">(</span><span style="color:#6200EE">name</span><span style="color:#222222">: </span><span style="color:#0C7064">"plugin-name"</span><span style="color:#222222">, </span><span style="color:#6200EE">type</span><span style="color:#222222">: .static, </span><span style="color:#6200EE">targets</span><span style="color:#222222">: [</span><span style="color:#0C7064">"plugin_name"</span><span style="color:#222222">])</span></span> <span class="line"><span style="color:#222222">],</span></span></code></pre></div></div></li><li><p>Make any other customizations. For more information on how to write a <code>Package.swift</code> file, see <a href="https://developer.apple.com/documentation/packagedescription">https://developer.apple.com/documentation/packagedescription</a>.</p><aside class="alert alert-success"><div class="alert-header"><i class="material-symbols" aria-hidden="true">lightbulb</i> <span>Tip</span></div><div class="alert-content"><p>If you add targets to your <code>Package.swift</code> file, use unique names. This avoids conflicts with targets from other packages.</p></div></aside></li></ol></li><li><p>Update your <code>ios/plugin_name.podspec</code> to point to new paths.</p><div class="code-block-wrapper language-ruby"><div class="code-block-header">ios/plugin_name.podspec</div><div class="code-block-body"><span class="code-block-language" title="Language ruby">ruby</span><pre class="shiki dash-light" tabindex="0"><code><span class="line removed-line"><span style="color:#222222">s.</span><span style="color:#6200EE">source_files</span><span style="color:#222222"> = </span><span style="color:#0C7064">'Classes/**/*.swift'</span></span> <span class="line removed-line"><span style="color:#222222">s.</span><span style="color:#6200EE">resource_bundles</span><span style="color:#222222"> = {</span><span style="color:#0C7064">'plugin_name_privacy'</span><span style="color:#222222"> => [</span><span style="color:#0C7064">'Resources/PrivacyInfo.xcprivacy'</span><span style="color:#222222">]}</span></span> <span class="line added-line"><span style="color:#222222">s.</span><span style="color:#6200EE">source_files</span><span style="color:#222222"> = </span><span style="color:#0C7064">'plugin_name/Sources/plugin_name/**/*.swift'</span></span> <span class="line added-line"><span style="color:#222222">s.</span><span style="color:#6200EE">resource_bundles</span><span style="color:#222222"> = {</span><span style="color:#0C7064">'plugin_name_privacy'</span><span style="color:#222222"> => [</span><span style="color:#0C7064">'plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacy'</span><span style="color:#222222">]}</span></span></code></pre></div></div></li><li><p>Update loading of resources from bundle to use <a href="https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package#Access-a-resource-in-code"><code>Bundle.module</code></a>.</p><div class="code-block-wrapper language-swift"><div class="code-block-body"><span class="code-block-language" title="Language swift">swift</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222">#</span><span style="color:#BD2314">if</span><span style="color:#222222"> SWIFT_PACKAGE</span></span> <span class="line"><span style="color:#BD2314"> let</span><span style="color:#222222"> settingsURL = Bundle.module.url(</span><span style="color:#6200EE">forResource</span><span style="color:#222222">: </span><span style="color:#0C7064">"image"</span><span style="color:#222222">, </span><span style="color:#6200EE">withExtension</span><span style="color:#222222">: </span><span style="color:#0C7064">"jpg"</span><span style="color:#222222">)</span></span> <span class="line"><span style="color:#222222">#</span><span style="color:#BD2314">else</span></span> <span class="line"><span style="color:#BD2314"> let</span><span style="color:#222222"> settingsURL = </span><span style="color:#6200EE">Bundle</span><span style="color:#222222">(</span><span style="color:#6200EE">for</span><span style="color:#222222">: </span><span style="color:#BD2314">Self</span><span style="color:#222222">.</span><span style="color:#BD2314">self</span><span style="color:#222222">).url(</span><span style="color:#6200EE">forResource</span><span style="color:#222222">: </span><span style="color:#0C7064">"image"</span><span style="color:#222222">, </span><span style="color:#6200EE">withExtension</span><span style="color:#222222">: </span><span style="color:#0C7064">"jpg"</span><span style="color:#222222">)</span></span> <span class="line"><span style="color:#222222">#</span><span style="color:#BD2314">endif</span></span></code></pre></div></div><aside class="alert alert-info"><div class="alert-header"><i class="material-symbols" aria-hidden="true">info</i> <span>Note</span></div><div class="alert-content"><p><code>Bundle.module</code> only works if there are resources <a href="https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package#Explicitly-declare-or-exclude-resources">defined in the <code>Package.swift</code> file</a> or <a href="https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package#:~:text=Xcode%20detects%20common%20resource%20types%20for%20Apple%20platforms%20and%20treats%20them%20as%20a%20resource%20automatically">automatically included by Xcode</a>). Otherwise, using <code>Bundle.module</code> results in an error.</p></div></aside></li><li><p>If your <code>.gitignore</code> doesn't include <code>.build/</code> and <code>.swiftpm/</code> directories, you'll want to update your <code>.gitignore</code> to include:</p><div class="code-block-wrapper language-text"><div class="code-block-header">.gitignore</div><div class="code-block-body"><span class="code-block-language" title="Language text">text</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span>.build/</span></span> <span class="line"><span>.swiftpm/</span></span></code></pre></div></div><p>Commit your plugin's changes to your version control system.</p></li><li><p>Verify the plugin still works with CocoaPods.</p><ol><li><p>Turn off Swift Package Manager.</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">flutter</span><span style="color:#0C7064"> config</span><span style="color:#0C7064"> --no-enable-swift-package-manager</span></span></code></pre></div></div></li><li><p>Navigate to the plugin's example app.</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">cd</span><span style="color:#0C7064"> path/to/plugin/example/</span></span></code></pre></div></div></li><li><p>Ensure the plugin's example app builds and runs.</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">flutter</span><span style="color:#0C7064"> run</span></span></code></pre></div></div></li><li><p>Navigate to the plugin's top-level directory.</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">cd</span><span style="color:#0C7064"> path/to/plugin/</span></span></code></pre></div></div></li><li><p>Run CocoaPods validation lints.</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">pod</span><span style="color:#0C7064"> lib</span><span style="color:#0C7064"> lint</span><span style="color:#0C7064"> ios/plugin_name.podspec</span><span style="color:#0C7064"> --configuration=Debug</span><span style="color:#0C7064"> --skip-tests</span><span style="color:#0C7064"> --use-modular-headers</span><span style="color:#0C7064"> --use-libraries</span></span></code></pre></div></div><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">pod</span><span style="color:#0C7064"> lib</span><span style="color:#0C7064"> lint</span><span style="color:#0C7064"> ios/plugin_name.podspec</span><span style="color:#0C7064"> --configuration=Debug</span><span style="color:#0C7064"> --skip-tests</span><span style="color:#0C7064"> --use-modular-headers</span></span></code></pre></div></div></li></ol></li><li><p>Verify the plugin works with Swift Package Manager.</p><ol><li><p>Turn on Swift Package Manager.</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">flutter</span><span style="color:#0C7064"> config</span><span style="color:#0C7064"> --enable-swift-package-manager</span></span></code></pre></div></div></li><li><p>Navigate to the plugin's example app.</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">cd</span><span style="color:#0C7064"> path/to/plugin/example/</span></span></code></pre></div></div></li><li><p>Ensure the plugin's example app builds and runs.</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">flutter</span><span style="color:#0C7064"> run</span></span></code></pre></div></div><aside class="alert alert-info"><div class="alert-header"><i class="material-symbols" aria-hidden="true">info</i> <span>Note</span></div><div class="alert-content"><p>Using the Flutter CLI to run the plugin's example app with the Swift Package Manager feature turned on migrates the project to add Swift Package Manager integration.</p><p>This raises the example app's Flutter SDK requirement to version 3.24 or higher.</p><p>If you'd like to run the example app using an older Flutter SDK version, do not commit the migration's changes to your version control system. If needed, you can always <a href="/packages-and-plugins/swift-package-manager/for-app-developers#how-to-remove-swift-package-manager-integration">undo the Swift Package Manager migration</a>.</p></div></aside></li><li><p>Open the plugin's example app in Xcode. Ensure that <strong>Package Dependencies</strong> shows in the left <strong>Project Navigator</strong>.</p></li></ol></li><li><p>Verify tests pass.</p><ul><li><p><strong>If your plugin has native unit tests (XCTest), make sure you also <a href="/packages-and-plugins/swift-package-manager/for-plugin-authors/#how-to-update-unit-tests-in-a-plugins-example-app">update unit tests in the plugin's example app</a>.</strong></p></li><li><p>Follow instructions for <a href="https://docs.flutter.dev/testing/testing-plugins">testing plugins</a>.</p></li></ul></li></ol></div><div class="tab-pane" id="114-tab-panel" role="tabpanel" aria-labelledby="114-tab"><p>Replace <code>plugin_name</code> throughout this guide with the name of your plugin. The example below uses <code>ios</code>, replace <code>ios</code> with <code>macos</code>/<code>darwin</code> as applicable.</p><ol><li><p><a href="/packages-and-plugins/swift-package-manager/for-plugin-authors#how-to-turn-on-swift-package-manager">Turn on the Swift Package Manager feature</a>.</p></li><li><p>Start by creating a directory under the <code>ios</code>, <code>macos</code>, and/or <code>darwin</code> directories. Name this new directory the name of the platform package.</p><pre> plugin_name/ios/ ├── ... └── <b>plugin_name/</b> </pre></li><li><p>Within this new directory, create the following files/directories:</p><ul><li><code>Package.swift</code> (file)</li><li><code>Sources</code> (directory)</li><li><code>Sources/plugin_name</code> (directory)</li><li><code>Sources/plugin_name/include</code> (directory)</li><li><code>Sources/plugin_name/include/plugin_name</code> (directory)</li><li><code>Sources/plugin_name/include/plugin_name/.gitkeep</code> (file)<ul><li>This file ensures the directory is committed. You can remove the <code>.gitkeep</code> file if other files are added to the directory.</li></ul></li></ul><p>Your plugin should look like:</p><pre> plugin_name/ios/ ├── ... └── plugin_name/ ├── <b>Package.swift</b> └── <b>Sources/plugin_name/include/plugin_name/</b> └── <b>.gitkeep</b> </pre></li><li><p>Use the following template in the <code>Package.swift</code> file:</p><div class="code-block-wrapper language-swift"><div class="code-block-header">Package.swift</div><div class="code-block-body"><span class="code-block-language" title="Language swift">swift</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6E6E70">// swift-tools-version: 5.9</span></span> <span class="line"><span style="color:#6E6E70">// The swift-tools-version declares the minimum version of Swift required to build this package.</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">import</span><span style="color:#0468D7"> PackageDescription</span></span> <span class="line"></span> <span class="line"><span style="color:#BD2314">let</span><span style="color:#BD2314"> package</span><span style="color:#222222"> = </span><span style="color:#6200EE">Package</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update your plugin name.</span></span> <span class="line"><span style="color:#6200EE"> name</span><span style="color:#222222">: </span><span style="color:#0C7064">"plugin_name"</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#6200EE"> platforms</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update the platforms your plugin supports.</span></span> <span class="line"><span style="color:#6E6E70"> // If your plugin only supports iOS, remove `.macOS(...)`.</span></span> <span class="line"><span style="color:#6E6E70"> // If your plugin only supports macOS, remove `.iOS(...)`.</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">iOS</span><span style="color:#222222">(</span><span style="color:#0C7064">"12.0"</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">macOS</span><span style="color:#222222">(</span><span style="color:#0C7064">"10.14"</span><span style="color:#222222">)</span></span> <span class="line"><span style="color:#222222"> ],</span></span> <span class="line"><span style="color:#6200EE"> products</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update your library and target names.</span></span> <span class="line"><span style="color:#6E6E70"> // If the plugin name contains "_", replace with "-" for the library name</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">library</span><span style="color:#222222">(</span><span style="color:#6200EE">name</span><span style="color:#222222">: </span><span style="color:#0C7064">"plugin-name"</span><span style="color:#222222">, </span><span style="color:#6200EE">targets</span><span style="color:#222222">: [</span><span style="color:#0C7064">"plugin_name"</span><span style="color:#222222">])</span></span> <span class="line"><span style="color:#222222"> ],</span></span> <span class="line"><span style="color:#6200EE"> dependencies</span><span style="color:#222222">: [],</span></span> <span class="line"><span style="color:#6200EE"> targets</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">target</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update your target name.</span></span> <span class="line"><span style="color:#6200EE"> name</span><span style="color:#222222">: </span><span style="color:#0C7064">"plugin_name"</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#6200EE"> dependencies</span><span style="color:#222222">: [],</span></span> <span class="line"><span style="color:#6200EE"> resources</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: If your plugin requires a privacy manifest</span></span> <span class="line"><span style="color:#6E6E70"> // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file</span></span> <span class="line"><span style="color:#6E6E70"> // to describe your plugin's privacy impact, and then uncomment this line.</span></span> <span class="line"><span style="color:#6E6E70"> // For more information, see:</span></span> <span class="line"><span style="color:#6E6E70"> // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files</span></span> <span class="line"><span style="color:#6E6E70"> // .process("PrivacyInfo.xcprivacy"),</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70"> // TODO: If you have other resources that need to be bundled with your plugin, refer to</span></span> <span class="line"><span style="color:#6E6E70"> // the following instructions to add them:</span></span> <span class="line"><span style="color:#6E6E70"> // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package</span></span> <span class="line"><span style="color:#222222"> ],</span></span> <span class="line"><span style="color:#6200EE"> cSettings</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update your plugin name.</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">headerSearchPath</span><span style="color:#222222">(</span><span style="color:#0C7064">"include/plugin_name"</span><span style="color:#222222">)</span></span> <span class="line"><span style="color:#222222"> ]</span></span> <span class="line"><span style="color:#222222"> )</span></span> <span class="line"><span style="color:#222222"> ]</span></span> <span class="line"><span style="color:#222222">)</span></span></code></pre></div></div></li><li><p>Update the <a href="https://developer.apple.com/documentation/packagedescription/supportedplatform">supported platforms</a> in your <code>Package.swift</code> file.</p><div class="code-block-wrapper language-swift"><div class="code-block-header">Package.swift</div><div class="code-block-body"><span class="code-block-language" title="Language swift">swift</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222"> platforms: [</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update the platforms your plugin supports.</span></span> <span class="line"><span style="color:#6E6E70"> // If your plugin only supports iOS, remove `.macOS(...)`.</span></span> <span class="line"><span style="color:#6E6E70"> // If your plugin only supports macOS, remove `.iOS(...)`.</span></span> <span class="line"><span style="color:#222222"> </span><mark class="highlight"><span style="color:#222222">.</span><span style="color:#6200EE">iOS</span><span style="color:#222222">(</span><span style="color:#0C7064">"12.0"</span><span style="color:#222222">),</span></mark></span> <span class="line"><span style="color:#222222"> </span><mark class="highlight"><span style="color:#222222">.</span><span style="color:#6200EE">macOS</span><span style="color:#222222">(</span><span style="color:#0C7064">"10.14"</span><span style="color:#222222">)</span></mark></span> <span class="line"><span style="color:#222222"> ],</span></span></code></pre></div></div></li><li><p>Update the package, library, and target names in your <code>Package.swift</code> file.</p><div class="code-block-wrapper language-swift"><div class="code-block-header">Package.swift</div><div class="code-block-body"><span class="code-block-language" title="Language swift">swift</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#BD2314">let</span><span style="color:#BD2314"> package</span><span style="color:#222222"> = </span><span style="color:#6200EE">Package</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update your plugin name.</span></span> <span class="line"><span style="color:#6200EE"> name</span><span style="color:#222222">: </span><mark class="highlight"><span style="color:#0C7064">"plugin_name"</span></mark><span style="color:#222222">,</span></span> <span class="line"><span style="color:#6200EE"> platforms</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">iOS</span><span style="color:#222222">(</span><span style="color:#0C7064">"12.0"</span><span style="color:#222222">),</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">macOS</span><span style="color:#222222">(</span><span style="color:#0C7064">"10.14"</span><span style="color:#222222">)</span></span> <span class="line"><span style="color:#222222"> ],</span></span> <span class="line"><span style="color:#6200EE"> products</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update your library and target names.</span></span> <span class="line"><span style="color:#6E6E70"> // If the plugin name contains "_", replace with "-" for the library name</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">library</span><span style="color:#222222">(</span><span style="color:#6200EE">name</span><span style="color:#222222">: </span><mark class="highlight"><span style="color:#0C7064">"plugin-name"</span></mark><span style="color:#222222">, </span><span style="color:#6200EE">targets</span><span style="color:#222222">: [</span><mark class="highlight"><span style="color:#0C7064">"plugin_name"</span></mark><span style="color:#222222">])</span></span> <span class="line"><span style="color:#222222"> ],</span></span> <span class="line"><span style="color:#6200EE"> dependencies</span><span style="color:#222222">: [],</span></span> <span class="line"><span style="color:#6200EE"> targets</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">target</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update your target name.</span></span> <span class="line"><span style="color:#6200EE"> name</span><span style="color:#222222">: </span><mark class="highlight"><span style="color:#0C7064">"plugin_name"</span></mark><span style="color:#222222">,</span></span> <span class="line"><span style="color:#6200EE"> dependencies</span><span style="color:#222222">: [],</span></span> <span class="line"><span style="color:#6200EE"> resources</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: If your plugin requires a privacy manifest</span></span> <span class="line"><span style="color:#6E6E70"> // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file</span></span> <span class="line"><span style="color:#6E6E70"> // to describe your plugin's privacy impact, and then uncomment this line.</span></span> <span class="line"><span style="color:#6E6E70"> // For more information, see:</span></span> <span class="line"><span style="color:#6E6E70"> // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files</span></span> <span class="line"><span style="color:#6E6E70"> // .process("PrivacyInfo.xcprivacy"),</span></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70"> // TODO: If you have other resources that need to be bundled with your plugin, refer to</span></span> <span class="line"><span style="color:#6E6E70"> // the following instructions to add them:</span></span> <span class="line"><span style="color:#6E6E70"> // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package</span></span> <span class="line"><span style="color:#222222"> ],</span></span> <span class="line"><span style="color:#6200EE"> cSettings</span><span style="color:#222222">: [</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: Update your plugin name.</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">headerSearchPath</span><span style="color:#222222">(</span><span style="color:#0C7064">"include/</span><mark class="highlight"><span style="color:#0C7064">plugin_name</span></mark><span style="color:#0C7064">"</span><span style="color:#222222">)</span></span> <span class="line"><span style="color:#222222"> ]</span></span> <span class="line"><span style="color:#222222"> )</span></span> <span class="line"><span style="color:#222222"> ]</span></span> <span class="line"><span style="color:#222222">)</span></span></code></pre></div></div><aside class="alert alert-info"><div class="alert-header"><i class="material-symbols" aria-hidden="true">info</i> <span>Note</span></div><div class="alert-content"><p>If the plugin name contains <code>_</code>, the library name must be a <code>-</code> separated version of the plugin name.</p></div></aside></li><li><p>If your plugin has a <a href="https://developer.apple.com/documentation/bundleresources/privacy_manifest_files"><code>PrivacyInfo.xcprivacy</code> file</a>, move it to <code>ios/plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacy</code> and uncomment the resource in the <code>Package.swift</code> file.</p><div class="code-block-wrapper language-swift"><div class="code-block-header">Package.swift</div><div class="code-block-body"><span class="code-block-language" title="Language swift">swift</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222"> resources: [</span></span> <span class="line"><span style="color:#6E6E70"> // TODO: If your plugin requires a privacy manifest</span></span> <span class="line"><span style="color:#6E6E70"> // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file</span></span> <span class="line"><span style="color:#6E6E70"> // to describe your plugin's privacy impact, and then uncomment this line.</span></span> <span class="line"><span style="color:#6E6E70"> // For more information, see:</span></span> <span class="line"><span style="color:#6E6E70"> // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files</span></span> <span class="line"><span style="color:#222222"> </span><mark class="highlight"><span style="color:#222222">.</span><span style="color:#6200EE">process</span><span style="color:#222222">(</span><span style="color:#0C7064">"PrivacyInfo.xcprivacy"</span><span style="color:#222222">),</span></mark></span> <span class="line"></span> <span class="line"><span style="color:#6E6E70"> // TODO: If you have other resources that need to be bundled with your plugin, refer to</span></span> <span class="line"><span style="color:#6E6E70"> // the following instructions to add them:</span></span> <span class="line"><span style="color:#6E6E70"> // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package</span></span> <span class="line"><span style="color:#222222"> ],</span></span></code></pre></div></div></li><li><p>Move any resource files from <code>ios/Assets</code> to <code>ios/plugin_name/Sources/plugin_name</code> (or a subdirectory). Add the resource files to your <code>Package.swift</code> file, if applicable. For more instructions, see <a href="https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package">https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package</a>.</p></li><li><p>Move any public headers from <code>ios/Classes</code> to <code>ios/plugin_name/Sources/plugin_name/include/plugin_name</code>.</p><ul><li><p>If you're unsure which headers are public, check your <code>podspec</code> file's <a href="https://guides.cocoapods.org/syntax/podspec.html#public_header_files"><code>public_header_files</code></a> attribute. If this attribute isn't specified, all of your headers were public. You should consider whether you want all of your headers to be public.</p></li><li><p>The <code>pluginClass</code> defined in your <code>pubspec.yaml</code> file must be public and within this directory.</p></li></ul></li><li><p>Handling <code>modulemap</code>.</p><p>Skip this step if your plugin does not have a <code>modulemap</code>.</p><p>If you're using a <code>modulemap</code> for CocoaPods to create a Test submodule, consider removing it for Swift Package Manager. Note that this makes all public headers available through the module.</p><p>To remove the <code>modulemap</code> for Swift Package Manager but keep it for CocoaPods, exclude the <code>modulemap</code> and umbrella header in the plugin's <code>Package.swift</code> file.</p><p>The example below assumes the <code>modulemap</code> and umbrella header are located in the <code>ios/plugin_name/Sources/plugin_name/include</code> directory.</p><div class="code-block-wrapper language-swift"><div class="code-block-header">Package.swift</div><div class="code-block-body"><span class="code-block-language" title="Language swift">swift</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222">.</span><span style="color:#6200EE">target</span><span style="color:#222222">(</span></span> <span class="line"><span style="color:#6200EE"> name</span><span style="color:#222222">: </span><span style="color:#0C7064">"plugin_name"</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#6200EE"> dependencies</span><span style="color:#222222">: [],</span></span> <span class="line added-line"><span style="color:#6200EE"> exclude</span><span style="color:#222222">: [</span><span style="color:#0C7064">"include/cocoapods_plugin_name.modulemap"</span><span style="color:#222222">, </span><span style="color:#0C7064">"include/plugin_name-umbrella.h"</span><span style="color:#222222">],</span></span></code></pre></div></div><p>If you want to keep your unit tests compatible with both CocoaPods and Swift Package Manager, you can try the following:</p><div class="code-block-wrapper language-objc"><div class="code-block-header">Tests/TestFile.m</div><div class="code-block-body"><span class="code-block-language" title="Language objc">objc</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222">@import plugin_name;</span></span> <span class="line removed-line"><span style="color:#222222">@import plugin_name.Test;</span></span> <span class="line added-line"><span style="color:#222222">#</span><span style="color:#BD2314">if</span><span style="color:#6200EE"> __has_include</span><span style="color:#222222">(<</span><span style="color:#6200EE">plugin_name</span><span style="color:#222222">/</span><span style="color:#6200EE">plugin_name</span><span style="color:#222222">-</span><span style="color:#6200EE">umbrella</span><span style="color:#222222">.</span><span style="color:#6200EE">h</span><span style="color:#222222">>)</span></span> <span class="line added-line"><span style="color:#222222"> @import plugin_name.Test;</span></span> <span class="line added-line"><span style="color:#222222">#</span><span style="color:#BD2314">endif</span></span></code></pre></div></div><p>If you would like to use a custom <code>modulemap</code> with your Swift package, refer to <a href="https://github.com/apple/swift-package-manager/blob/main/Documentation/Usage.md#creating-c-language-targets">Swift Package Manager's documentation</a>.</p></li><li><p>Move all remaining files from <code>ios/Classes</code> to <code>ios/plugin_name/Sources/plugin_name</code>.</p></li><li><p>The <code>ios/Assets</code>, <code>ios/Resources</code>, and <code>ios/Classes</code> directories should now be empty and can be deleted.</p></li><li><p>If your header files are no longer in the same directory as your implementation files, you should update your import statements.</p><p>For example, imagine the following migration:</p><ul><li><p>Before:</p><pre> ios/Classes/ ├── PublicHeaderFile.h └── ImplementationFile.m </pre></li><li><p>After:</p><pre> ios/plugin_name/Sources/plugin_name/ └── <b>include/plugin_name/</b> └── PublicHeaderFile.h └── ImplementationFile.m </pre></li></ul><p>In this example, the import statements in <code>ImplementationFile.m</code> should be updated:</p><div class="code-block-wrapper language-objc"><div class="code-block-header">Sources/plugin_name/ImplementationFile.m</div><div class="code-block-body"><span class="code-block-language" title="Language objc">objc</span><pre class="shiki dash-light" tabindex="0"><code><span class="line removed-line"><span style="color:#222222">#</span><span style="color:#BD2314">import</span><span style="color:#0C7064"> "PublicHeaderFile.h"</span></span> <span class="line added-line"><span style="color:#222222">#</span><span style="color:#BD2314">import</span><span style="color:#0C7064"> "./include/plugin_name/PublicHeaderFile.h"</span></span></code></pre></div></div></li><li><p>If your plugin uses <a href="https://pub.dev/packages/pigeon">Pigeon</a>, update your Pigeon input file.</p><div class="code-block-wrapper language-dart"><div class="code-block-header">pigeons/messages.dart</div><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222">javaOptions: </span><span style="color:#0468D7">JavaOptions</span><span style="color:#222222">(),</span></span> <span class="line removed-line"><span style="color:#222222">objcHeaderOut: </span><span style="color:#0C7064">'ios/Classes/messages.g.h'</span><span style="color:#222222">,</span></span> <span class="line removed-line"><span style="color:#222222">objcSourceOut: </span><span style="color:#0C7064">'ios/Classes/messages.g.m'</span><span style="color:#222222">,</span></span> <span class="line added-line"><span style="color:#222222">objcHeaderOut: </span><span style="color:#0C7064">'ios/plugin_name/Sources/plugin_name/messages.g.h'</span><span style="color:#222222">,</span></span> <span class="line added-line"><span style="color:#222222">objcSourceOut: </span><span style="color:#0C7064">'ios/plugin_name/Sources/plugin_name/messages.g.m'</span><span style="color:#222222">,</span></span> <span class="line"><span style="color:#222222">copyrightHeader: </span><span style="color:#0C7064">'pigeons/copyright.txt'</span><span style="color:#222222">,</span></span></code></pre></div></div><p>If your <code>objcHeaderOut</code> file is no longer within the same directory as the <code>objcSourceOut</code>, you can change the <code>#import</code> using <code>ObjcOptions.headerIncludePath</code>:</p><div class="code-block-wrapper language-dart"><div class="code-block-header">pigeons/messages.dart</div><div class="code-block-body"><span class="code-block-language" title="Language dart">dart</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222">javaOptions: </span><span style="color:#0468D7">JavaOptions</span><span style="color:#222222">(),</span></span> <span class="line removed-line"><span style="color:#222222">objcHeaderOut: </span><span style="color:#0C7064">'ios/Classes/messages.g.h'</span><span style="color:#222222">,</span></span> <span class="line removed-line"><span style="color:#222222">objcSourceOut: </span><span style="color:#0C7064">'ios/Classes/messages.g.m'</span><span style="color:#222222">,</span></span> <span class="line added-line"><span style="color:#222222">objcHeaderOut: </span><span style="color:#0C7064">'ios/plugin_name/Sources/plugin_name/include/plugin_name/messages.g.h'</span><span style="color:#222222">,</span></span> <span class="line added-line"><span style="color:#222222">objcSourceOut: </span><span style="color:#0C7064">'ios/plugin_name/Sources/plugin_name/messages.g.m'</span><span style="color:#222222">,</span></span> <span class="line added-line"><span style="color:#222222">objcOptions: </span><span style="color:#0468D7">ObjcOptions</span><span style="color:#222222">(</span></span> <span class="line added-line"><span style="color:#222222"> headerIncludePath: </span><span style="color:#0C7064">'./include/plugin_name/messages.g.h'</span><span style="color:#222222">,</span></span> <span class="line added-line"><span style="color:#222222">),</span></span> <span class="line"><span style="color:#222222">copyrightHeader: </span><span style="color:#0C7064">'pigeons/copyright.txt'</span><span style="color:#222222">,</span></span></code></pre></div></div><p>Run Pigeon to re-generate its code with the latest configuration.</p></li><li><p>Update your <code>Package.swift</code> file with any customizations you might need.</p><ol><li><p>Open the <code>ios/plugin_name/</code> directory in Xcode.</p></li><li><p>In Xcode, open your <code>Package.swift</code> file. Verify Xcode doesn't produce any warnings or errors for this file.</p><aside class="alert alert-success"><div class="alert-header"><i class="material-symbols" aria-hidden="true">lightbulb</i> <span>Tip</span></div><div class="alert-content"><p>If Xcode doesn't show any files, quit Xcode (<strong>Xcode > Quit Xcode</strong>) and reopen.</p><p>If Xcode doesn't update after you make a change, try clicking <strong>File > Packages > Reset Package Caches</strong>.</p></div></aside></li><li><p>If your <code>ios/plugin_name.podspec</code> file has <a href="https://guides.cocoapods.org/syntax/podspec.html#dependency">CocoaPods <code>dependency</code></a>s, add the corresponding <a href="https://developer.apple.com/documentation/packagedescription/package/dependency">Swift Package Manager dependencies</a> to your <code>Package.swift</code> file.</p></li><li><p>If your package must be linked explicitly <code>static</code> or <code>dynamic</code> (<a href="https://developer.apple.com/documentation/packagedescription/product/library(name:type:targets:)">not recommended by Apple</a>), update the <a href="https://developer.apple.com/documentation/packagedescription/product">Product</a> to define the type:</p><div class="code-block-wrapper language-swift"><div class="code-block-header">Package.swift</div><div class="code-block-body"><span class="code-block-language" title="Language swift">swift</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222">products: [</span></span> <span class="line"><span style="color:#222222"> .</span><span style="color:#6200EE">library</span><span style="color:#222222">(</span><span style="color:#6200EE">name</span><span style="color:#222222">: </span><span style="color:#0C7064">"plugin-name"</span><span style="color:#222222">, </span><span style="color:#6200EE">type</span><span style="color:#222222">: .static, </span><span style="color:#6200EE">targets</span><span style="color:#222222">: [</span><span style="color:#0C7064">"plugin_name"</span><span style="color:#222222">])</span></span> <span class="line"><span style="color:#222222">],</span></span></code></pre></div></div></li><li><p>Make any other customizations. For more information on how to write a <code>Package.swift</code> file, see <a href="https://developer.apple.com/documentation/packagedescription">https://developer.apple.com/documentation/packagedescription</a>.</p><aside class="alert alert-success"><div class="alert-header"><i class="material-symbols" aria-hidden="true">lightbulb</i> <span>Tip</span></div><div class="alert-content"><p>If you add targets to your <code>Package.swift</code> file, use unique names. This avoids conflicts with targets from other packages.</p></div></aside></li></ol></li><li><p>Update your <code>ios/plugin_name.podspec</code> to point to new paths.</p><div class="code-block-wrapper language-ruby"><div class="code-block-header">ios/plugin_name.podspec</div><div class="code-block-body"><span class="code-block-language" title="Language ruby">ruby</span><pre class="shiki dash-light" tabindex="0"><code><span class="line removed-line"><span style="color:#222222">s.</span><span style="color:#6200EE">source_files</span><span style="color:#222222"> = </span><span style="color:#0C7064">'Classes/**/*.{h,m}'</span></span> <span class="line removed-line"><span style="color:#222222">s.</span><span style="color:#6200EE">public_header_files</span><span style="color:#222222"> = </span><span style="color:#0C7064">'Classes/**/*.h'</span></span> <span class="line removed-line"><span style="color:#222222">s.</span><span style="color:#6200EE">module_map</span><span style="color:#222222"> = </span><span style="color:#0C7064">'Classes/cocoapods_plugin_name.modulemap'</span></span> <span class="line removed-line"><span style="color:#222222">s.</span><span style="color:#6200EE">resource_bundles</span><span style="color:#222222"> = {</span><span style="color:#0C7064">'plugin_name_privacy'</span><span style="color:#222222"> => [</span><span style="color:#0C7064">'Resources/PrivacyInfo.xcprivacy'</span><span style="color:#222222">]}</span></span> <span class="line added-line"><span style="color:#222222">s.</span><span style="color:#6200EE">source_files</span><span style="color:#222222"> = </span><span style="color:#0C7064">'plugin_name/Sources/plugin_name/**/*.{h,m}'</span></span> <span class="line added-line"><span style="color:#222222">s.</span><span style="color:#6200EE">public_header_files</span><span style="color:#222222"> = </span><span style="color:#0C7064">'plugin_name/Sources/plugin_name/include/**/*.h'</span></span> <span class="line added-line"><span style="color:#222222">s.</span><span style="color:#6200EE">module_map</span><span style="color:#222222"> = </span><span style="color:#0C7064">'plugin_name/Sources/plugin_name/include/cocoapods_plugin_name.modulemap'</span></span> <span class="line added-line"><span style="color:#222222">s.</span><span style="color:#6200EE">resource_bundles</span><span style="color:#222222"> = {</span><span style="color:#0C7064">'plugin_name_privacy'</span><span style="color:#222222"> => [</span><span style="color:#0C7064">'plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacy'</span><span style="color:#222222">]}</span></span></code></pre></div></div></li><li><p>Update loading of resources from bundle to use <code>SWIFTPM_MODULE_BUNDLE</code>:</p><div class="code-block-wrapper language-objc"><div class="code-block-body"><span class="code-block-language" title="Language objc">objc</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222">#</span><span style="color:#BD2314">if</span><span style="color:#6200EE"> SWIFT_PACKAGE</span></span> <span class="line"><span style="color:#0468D7"> NSBundle</span><span style="color:#222222"> *bundle = SWIFTPM_MODULE_BUNDLE;</span></span> <span class="line"><span style="color:#222222"> #</span><span style="color:#BD2314">else</span></span> <span class="line"><span style="color:#0468D7"> NSBundle</span><span style="color:#222222"> *bundle = [</span><span style="color:#0468D7">NSBundle</span><span style="color:#6200EE"> bundleForClass</span><span style="color:#222222">:[</span><span style="color:#BD2314">self</span><span style="color:#6200EE"> class</span><span style="color:#222222">]];</span></span> <span class="line"><span style="color:#222222"> #</span><span style="color:#BD2314">endif</span></span> <span class="line"><span style="color:#0468D7"> NSURL</span><span style="color:#222222"> *imageURL = [bundle </span><span style="color:#6200EE">URLForResource</span><span style="color:#222222">:</span><span style="color:#0C7064">@"image"</span><span style="color:#6200EE"> withExtension</span><span style="color:#222222">:</span><span style="color:#0C7064">@"jpg"</span><span style="color:#222222">];</span></span></code></pre></div></div><aside class="alert alert-info"><div class="alert-header"><i class="material-symbols" aria-hidden="true">info</i> <span>Note</span></div><div class="alert-content"><p><code>SWIFTPM_MODULE_BUNDLE</code> only works if there are actual resources (either <a href="https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package#Explicitly-declare-or-exclude-resources">defined in the <code>Package.swift</code> file</a> or <a href="https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package#:~:text=Xcode%20detects%20common%20resource%20types%20for%20Apple%20platforms%20and%20treats%20them%20as%20a%20resource%20automatically">automatically included by Xcode</a>). Otherwise, using <code>SWIFTPM_MODULE_BUNDLE</code> results in an error.</p></div></aside></li><li><p>If your <code>ios/plugin_name/Sources/plugin_name/include</code> directory only contains a <code>.gitkeep</code>, you'll want update your <code>.gitignore</code> to include the following:</p><div class="code-block-wrapper language-text"><div class="code-block-header">.gitignore</div><div class="code-block-body"><span class="code-block-language" title="Language text">text</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span>!.gitkeep</span></span></code></pre></div></div><p>Run <code>flutter pub publish --dry-run</code> to ensure the <code>include</code> directory is published.</p></li><li><p>Commit your plugin's changes to your version control system.</p></li><li><p>Verify the plugin still works with CocoaPods.</p><ol><li><p>Turn off Swift Package Manager:</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">flutter</span><span style="color:#0C7064"> config</span><span style="color:#0C7064"> --no-enable-swift-package-manager</span></span></code></pre></div></div></li><li><p>Navigate to the plugin's example app.</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">cd</span><span style="color:#0C7064"> path/to/plugin/example/</span></span></code></pre></div></div></li><li><p>Ensure the plugin's example app builds and runs.</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">flutter</span><span style="color:#0C7064"> run</span></span></code></pre></div></div></li><li><p>Navigate to the plugin's top-level directory.</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">cd</span><span style="color:#0C7064"> path/to/plugin/</span></span></code></pre></div></div></li><li><p>Run CocoaPods validation lints:</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">pod</span><span style="color:#0C7064"> lib</span><span style="color:#0C7064"> lint</span><span style="color:#0C7064"> ios/plugin_name.podspec</span><span style="color:#0C7064"> --configuration=Debug</span><span style="color:#0C7064"> --skip-tests</span><span style="color:#0C7064"> --use-modular-headers</span><span style="color:#0C7064"> --use-libraries</span></span></code></pre></div></div><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">pod</span><span style="color:#0C7064"> lib</span><span style="color:#0C7064"> lint</span><span style="color:#0C7064"> ios/plugin_name.podspec</span><span style="color:#0C7064"> --configuration=Debug</span><span style="color:#0C7064"> --skip-tests</span><span style="color:#0C7064"> --use-modular-headers</span></span></code></pre></div></div></li></ol></li><li><p>Verify the plugin works with Swift Package Manager.</p><ol><li><p>Turn on Swift Package Manager:</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">flutter</span><span style="color:#0C7064"> config</span><span style="color:#0C7064"> --enable-swift-package-manager</span></span></code></pre></div></div></li><li><p>Navigate to the plugin's example app.</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">cd</span><span style="color:#0C7064"> path/to/plugin/example/</span></span></code></pre></div></div></li><li><p>Ensure the plugin's example app builds and runs.</p><div class="code-block-wrapper language-sh"><div class="code-block-body"><span class="code-block-language" title="Language sh">sh</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#6200EE">flutter</span><span style="color:#0C7064"> run</span></span></code></pre></div></div><aside class="alert alert-info"><div class="alert-header"><i class="material-symbols" aria-hidden="true">info</i> <span>Note</span></div><div class="alert-content"><p>Using the Flutter CLI to run the plugin's example app with the Swift Package Manager feature turned on migrates the project to add Swift Package Manager integration.</p><p>This raises the example app's Flutter SDK requirement to version 3.24 or higher.</p><p>If you'd like to run the example app using an older Flutter SDK version, do not commit the migration's changes to your version control system. If needed, you can always <a href="/packages-and-plugins/swift-package-manager/for-app-developers#how-to-remove-swift-package-manager-integration">undo the Swift Package Manager migration</a>.</p></div></aside></li><li><p>Open the plugin's example app in Xcode. Ensure that <strong>Package Dependencies</strong> shows in the left <strong>Project Navigator</strong>.</p></li></ol></li><li><p>Verify tests pass.</p><ul><li><p><strong>If your plugin has native unit tests (XCTest), make sure you also <a href="/packages-and-plugins/swift-package-manager/for-plugin-authors/#how-to-update-unit-tests-in-a-plugins-example-app">update unit tests in the plugin's example app</a>.</strong></p></li><li><p>Follow instructions for <a href="https://docs.flutter.dev/testing/testing-plugins">testing plugins</a>.</p></li></ul></li></ol></div></div></div><div class="header-wrapper"><h2 id="how-to-update-unit-tests-in-a-plugins-example-app">How to update unit tests in a plugin's example app</h2><a class="heading-link" href="#how-to-update-unit-tests-in-a-plugins-example-app" aria-label="Link to 'How to update unit tests in a plugin's example app' section">#</a></div><p>If your plugin has native XCTests, you might need to update them to work with Swift Package Manager if one of the following is true:</p><ul><li>You're using a CocoaPod dependency for the test.</li><li>Your plugin is explicitly set to <code>type: .dynamic</code> in its <code>Package.swift</code> file.</li></ul><p>To update your unit tests:</p><ol><li><p>Open your <code>example/ios/Runner.xcworkspace</code> in Xcode.</p></li><li><p>If you were using a CocoaPod dependency for tests, such as <code>OCMock</code>, you'll want to remove it from your <code>Podfile</code> file.</p><div class="code-block-wrapper language-ruby"><div class="code-block-header">ios/Podfile</div><div class="code-block-body"><span class="code-block-language" title="Language ruby">ruby</span><pre class="shiki dash-light" tabindex="0"><code><span class="line"><span style="color:#222222">target </span><span style="color:#0C7064">'RunnerTests'</span><span style="color:#BD2314"> do</span></span> <span class="line"><span style="color:#222222"> inherit! :</span><span style="color:#0C7064">search_paths</span></span> <span class="line"></span> <span class="line removed-line"><span style="color:#222222"> pod </span><span style="color:#0C7064">'OCMock'</span><span style="color:#222222">, </span><span style="color:#0C7064">'3.5'</span></span> <span class="line"><span style="color:#BD2314">end</span></span></code></pre></div></div><p>Then in the terminal, run <code>pod install</code> in the <code>plugin_name_ios/example/ios</code> directory.</p></li><li><p>Navigate to <strong>Package Dependencies</strong> for the project.</p><p><img src="/assets/images/docs/development/packages-and-plugins/swift-package-manager/package-dependencies.png" alt="The project's package dependencies" title="The project's package dependencies" class="img-class"><br><figurecaption class="figure-caption">The project's package dependencies</figurecaption></p></li><li><p>Click the <strong>+</strong> button and add any test-only dependencies by searching for them in the top right search bar.</p><p><img src="/assets/images/docs/development/packages-and-plugins/swift-package-manager/search-for-ocmock.png" alt="Search for test-only dependencies" title="Search for test-only dependencies" class="img-class"><br><figurecaption class="figure-caption">Search for test-only dependencies</figurecaption></p><aside class="alert alert-info"><div class="alert-header"><i class="material-symbols" aria-hidden="true">info</i> <span>Note</span></div><div class="alert-content"><p>OCMock uses unsafe build flags and can only be used if targeted by commit. <code>fe1661a3efed11831a6452f4b1a0c5e6ddc08c3d</code> is the commit for the 3.9.3 version.</p></div></aside></li><li><p>Ensure the dependency is added to the <code>RunnerTests</code> Target.</p><p><img src="/assets/images/docs/development/packages-and-plugins/swift-package-manager/choose-package-products-test.png" alt="Ensure the dependency is added to the target" title="Ensure the dependency is added to the `RunnerTests` target" class="img-class"><br><figurecaption class="figure-caption">Ensure the dependency is added to the <code>RunnerTests</code> target</figurecaption></p></li><li><p>Click the <strong>Add Package</strong> button.</p></li><li><p>If you've explicitly set your plugin's library type to <code>.dynamic</code> in its <code>Package.swift</code> file (<a href="https://developer.apple.com/documentation/packagedescription/product/library(name:type:targets:)">not recommended by Apple</a>), you'll also need to add it as a dependency to the <code>RunnerTests</code> target.</p><ol><li><p>Ensure <code>RunnerTests</code> <strong>Build Phases</strong> has a <strong>Link Binary With Libraries</strong> build phase:</p><p><img src="/assets/images/docs/development/packages-and-plugins/swift-package-manager/runner-tests-link-binary-with-libraries.png" alt="The Build Phase in the target" title="The `Link Binary With Libraries` Build Phase in the `RunnerTests` target" class="img-class"><br><figurecaption class="figure-caption">The <code>Link Binary With Libraries</code> Build Phase in the <code>RunnerTests</code> target</figurecaption></p><p>If the build phase doesn't exist already, create one. Click the <span class="material-symbols">add</span> and then click <strong>New Link Binary With Libraries Phase</strong>.</p><p><img src="/assets/images/docs/development/packages-and-plugins/swift-package-manager/add-runner-tests-link-binary-with-libraries.png" alt="Add Build Phase" title="Add `Link Binary With Libraries` Build Phase" class="img-class"><br><figurecaption class="figure-caption">Add <code>Link Binary With Libraries</code> Build Phase</figurecaption></p></li><li><p>Navigate to <strong>Package Dependencies</strong> for the project.</p></li><li><p>Click <span class="material-symbols">add</span>.</p></li><li><p>In the dialog that opens, click the <strong>Add Local...</strong> button.</p></li><li><p>Navigate to <code>plugin_name/plugin_name_ios/ios/plugin_name_ios</code> and click the <strong>Add Package</strong> button.</p></li><li><p>Ensure that it's added to the <code>RunnerTests</code> target and click the <strong>Add Package</strong> button.</p></li></ol></li><li><p>Ensure tests pass <strong>Product > Test</strong>.</p></li></ol><p id="page-github-links"><span>Unless stated otherwise, the documentation on this site reflects the latest stable version of Flutter. Page last updated on 2024-12-13.</span> <a href="https://github.com/flutter/website/tree/main/src/content/packages-and-plugins/swift-package-manager/for-plugin-authors.md" target="_blank" rel="noopener">View source</a> <span>or </span><a href="https://github.com/flutter/website/issues/new?template=1_page_issue.yml&&page-url=https://docs.flutter.dev/packages-and-plugins/swift-package-manager/for-plugin-authors/&page-source=https://github.com/flutter/website/tree/main/src/content/packages-and-plugins/swift-package-manager/for-plugin-authors.md" title="Report an issue with this page" target="_blank" rel="noopener">report an issue</a>.</p></article></main></div><footer id="site-footer"><div class="footer-section footer-main"><a class="brand" href="https://flutter.dev"><img src="/assets/images/branding/flutter/logo+text/horizontal/white.svg" alt="Flutter logo" width="164"></a><div class="footer-social-links"><a class="icon-button" href="https://medium.com/flutter" target="_blank" rel="noopener" title="Flutter's Medium blog"><svg><use href="/assets/images/social/medium.svg#medium"></use></svg> </a><a class="icon-button" href="https://youtube.com/@flutterdev" target="_blank" rel="noopener" title="Flutter's YouTube"><svg><use href="/assets/images/social/youtube.svg#youtube"></use></svg> </a><a class="icon-button" href="https://github.com/flutter" target="_blank" rel="noopener" title="Flutter's GitHub"><svg><use href="/assets/images/social/github.svg#github"></use></svg> </a><a class="icon-button" href="https://bsky.app/profile/flutter.dev" target="_blank" rel="noopener" title="Flutter's Bluesky"><svg><use href="/assets/images/social/bluesky.svg#bluesky"></use></svg> </a><a class="icon-button" href="https://twitter.com/FlutterDev" target="_blank" rel="noopener" title="Flutter's X (Twitter)"><svg><use href="/assets/images/social/x.svg#x"></use></svg></a></div></div><div class="footer-section footer-tray"><div class="footer-licenses">Except as otherwise noted, this site is licensed under a <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>, and code samples are licensed under the <a href="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</a>.</div><div class="footer-utility-links"><ul><li><a href="/tos" title="Terms of use">Terms</a></li><li><a href="/brand" title="Brand usage guidelines">Brand</a></li><li><a href="https://policies.google.com/privacy" target="_blank" rel="noopener" title="Privacy policy">Privacy</a></li><li><a href="/security" title="Security philosophy and practices">Security</a></li></ul></div></div></footer></div><script src="/assets/js/tabs.js?v=4"></script><script src="/assets/js/archive.js?v=4"></script><script src="/assets/js/main.js?v=4"></script></body></html>