Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Swift Package Manager support #1368

Open
loic-sharma opened this issue Nov 19, 2024 · 4 comments
Open

Add Swift Package Manager support #1368

loic-sharma opened this issue Nov 19, 2024 · 4 comments
Assignees
Labels
1 backlog enhancement New feature or request

Comments

@loic-sharma
Copy link

Is your feature request related to a problem? Please describe.

Hello,

Flutter is migrating to Swift Package Manager. Please add Swift Package Manager support to your plugin.

Flutter will eventually deprecate and then remove support for CocoaPods. Adding Swift Package Manager support future-proofs your plugins.

How to add Swift Package Manager support to your plugins

You can find the migration guide here: https://docs.flutter.dev/packages-and-plugins/swift-package-manager/for-plugin-authors#how-to-add-swift-package-manager-support-to-an-existing-flutter-plugin

If you run into issues or have questions, please reach out to the Flutter team. You can ping me at @loic-sharma, send a message to the #hackers-ios channel on Flutter’s discord, or open a GitHub issue.

Thank you for your wonderful contributions to the Flutter ecosystem!

Why is Flutter migrating to Swift Package Manager?

CocoaPods is now in maintenance mode.

Swift Package Manager support is one of Flutter’s most requested features: flutter#33850.

Flutter's Swift Package Manager integration has several benefits:

  1. Access to the Swift package ecosystem. Flutter plugins can use the growing ecosystem of Swift packages.
  2. Simplifies Flutter installation. Swift Package Manager is bundled with Xcode. In the future, you won’t need to install Ruby and CocoaPods to target iOS or macOS.

Describe the solution you'd like
Add Swift Package Manager support to just_audio.

Describe alternatives you've considered
N/A

Additional context
N/A

@ryanheise
Copy link
Owner

Thanks @loic-sharma , it's on my list. We use macros in the Podfile to compile in/out certain code:

https://pub.dev/packages/just_audio#ios

This is necessary because the App Store's static analyzer will check your compiled binary to see if it's using any sensitive APIs like the microphone, and if so, it flags it down and requires you to declare a reason for using the microphone, and this then gets alerted to the user. Some apps may wish to "compile out" the microphone code so as not to trigger this.

Do you have any tips on how to migrate this?

@loic-sharma
Copy link
Author

Sadly, I don't think there's a good way to do this using SwiftPM today. The SwiftPM team has a proposal that would let you do this, but it's unclear when this will land. I think the best option today would be to create a separate plugin that excludes the microphone code.

@ryanheise
Copy link
Owner

That's going to have some undesirable implications for the flutter ecosystem. For example, permission_handler would need to be split into at least 13 plugins.

What's the timeline on this? Do you propose that affected plugins split now, or wait for a better solution before migrating to SwiftPM?

As for my package, the issue is really in audio_session which wraps the AVAudioSession API and exposes the AVAudioSessionCategory enum:

enum AVAudioSessionCategory {
  ambient,
  soloAmbient,
  playback,
  record,
  playAndRecord,
  multiRoute,
}

and an API for setting the category on the audio session:

Future<void> setCategory(AVAudioSessionCategory? category)

So as to avoid messing up this API by splitting the method into two, I could keep the surface API as is and have the main plugin be extensible where a second package provides the microphone extension which, when installed, will allow this same API to function on the microphone-related enums.

But before I mess about with this breaking change, it would help to have a grand plan going forward so that I don't introduce breaking changes and then introduce more breaking changes down the line.

@loic-sharma
Copy link
Author

What's the timeline on this? Do you propose that affected plugins split now, or wait for a better solution before migrating to SwiftPM?

We don't have a timeline yet. However, maintaining support for two package managers (CocoaPods & SwiftPM) is a serious maintenance burden for the Flutter team. We will remove CocoaPods support as soon as possible - if I had to guess, that'd be ~1 year from now.


I experimented with SwiftPM and it turns out it's possible to do conditional compilation using hacks.

In your Package.swift file, you can define a conditional compilation if an environment variable is set:

 // swift-tools-version: 5.9
 // The swift-tools-version declares the minimum version of Swift required to build this package.
 
 import PackageDescription
+import Foundation
+
+var swiftSettings: [SwiftSetting] = []
+
+if ProcessInfo.processInfo.environment["MY_ENVIRONMENT_VARIABLE"] == "1" {
+    swiftSettings.append(.define("MY_FEATURE_ENABLED"))
+}
     
 let package = Package(
    name: "my_plugin",
    platforms: [],
    products: [],
    dependencies: [],
    targets: [
        .target(
            name: "my_plugin",
            dependencies: [],
-            resources: []
+            resources: [],
+            swiftSettings: swiftSettings
        )
    ]
)

Users can now opt-in to the conditional compilation:

  1. Clean your previous compilation to rebuild your Swift package.

    flutter clean

    This step must be done each time you change the value of MY_ENVIRONMENT_VARIABLE.
    Xcode is not smart enough to rebuild your Swift package when MY_ENVIRONMENT_VARIABLE changes.

  2. Run your app with the MY_ENVIRONMENT_VARIABLE environment variable.

    Using the command line:

    MY_ENVIRONMENT_VARIABLE=1 flutter run
    

    Or, using VS Code launch configurations:

    {
      "configurations": [
        {
          "name": "Flutter",
          "request": "launch",
          "type": "dart",
          "env": {
            "MY_ENVIRONMENT_VARIABLE": "1"
          }
       }
     ]
    }

I created an example app that shows this technique.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1 backlog enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants