Let’s say you’re writing the IOS component of a Flutter plugin in Swift.
You have your MyFlutterPlugin.swift file open in XCode.
So that we know what we’re talking about the same thing, it’s the file that looks like this:
public class MyFlutterPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "my_flutter_plugin", binaryMessenger: registrar.messenger())
let instance = SwiftMetronomeFlutterPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
// ...
}
}
This file exists on disk at:
[your_plugin_project_name]/ios/classes/MyFlutterPlugin.swift
How could you add a resource, for example an audio (WAV) file, such that it could be referenced from within MyFlutterPlugin.swift?
In a normal (not Flutter) IOS app, I have accomplished this by simply dragging the WAV file into XCode where it sits alongside ViewController.swift (in the same folder), and referenced it from within the ViewController like this:
let clack_Path = Bundle.main.path(forResource: "clack", ofType: "wav")
let clack_URL = URL(fileURLWithPath: clack_Path!)
But, if I try that same approach from within MyFlutterPlugin.swift (putting the audio file alongside MyFlutterPlugin.swift), I get an error that clack_Path is null.
So where is the correct place to put the file, and how to properly reference it?
I can’t find any code examples, tutorials, or documentation (at least not any that I recognize as being useful) on this specific problem. Hopefully it’s actually possible to do on IOS… I’ve already got the resources included and working on the Android side of the plugin.
2
Answers
Try this: https://docs.flutter.dev/development/ui/assets-and-images#loading-flutter-assets-in-ios
In short, firstly, put your file as a normal Flutter asset (instead of ios/android asset). Then, use the approach in the link to access it.
To be able to use assets in the Flutter Plugin, firstly, we need to add the resources inside the plugins’s folder, in this example, I am placing the
clap.wav
file in the folder[your_plugin_project_name]/ios/Assets/
.After adding the file inside the plugin’s folder, we need to specify in the plugin’s PodSpec where the assets are located.
The important part in the snippet above is the line
s.resources = ['Assets/**.*']
, whereAssets/**/*
specify that all the plugin’s resources are inside the folderAssets
. TheAssets/**/*
is a wildcard used to tell that every file (the*
string part) in every folder/subfolder (the**
part) within the folderAssets
must be included as resources of the plugin’s bundle. You can learn more about this kind of string searching aboutregular expression
.Every time you change the plugin’s configuration, you’ll need to inform the Flutter’s project using the plugin that there are new changes. In a regular project, you would need to bump the plugin’s version and release a new version of it in the Pub, but as we are just changing this locally (without releasing it to the world), we need only to inform Flutter that the plugin’s files are outdated. The easiest way to do that is to run
flutter clean
inside the project that is using the plugin.After that, you will be able to access the
clap.wav
file in the plugins’s swift files using the code:Notice that you must use
Bundle(for: type(of: self))
instead ofBundle.main
(theBundle.main
points to the Runner’s bundle instead of your plugin’s bundle).I the example below, I show how you could play the
clap.wav
using swift code:The example above is a simple example of how you could play the
clap.wav
file, but you could do in different other ways. As this is not related with the question, I think that the example above is enough to answer your question.To facilitate your understanding and easily demonstrate that the code above works, I created a simple project in the GitHub that you can execute to see that this works as expected, see it here.
Notice that you must run the code inside the folder
example
.