I'm trying to write a Swift package that uses a CoreML model. I'm not very familiar with Swift packages creation and I could not make it work. Here is what I've done based on the different posts I've read so far:
- Create an empty package
$ mkdir MyPackage
$ cd MyPackage
$ swift package init
$ swift build
$ swift test
Open the
Package.swift
file with XCodeDrag and drop the
MyModel.mlmodel
file into the folderSources/MyPackage
When I click on the MyModel.mlmodel
file in XCode, I have the following message displayed under the class name:
Model is not part of any target. Add the model to a target to enable generation of the model class.
Similarly, if I use the command swift build
in a Terminal I get the following message:
warning: found 1 file(s) which are unhandled; explicitly declare them as resources or exclude from the target
/Path/To/MyPackage/Sources/MyPackage/MyModel.mlmodel
- To solve this, I added
MyModel
into the target resources in the filePackage.swift
:
.target(
name: "MyPackage",
dependencies: [],
resources: [.process("MyModel.mlmodel")]),
If I now use the command $ swift build
, I don't have the warning anymore and I get the message:
[3/3] Merging module MyPackage
But when I check the MyModel.mlmodel
file in XCode, I have the following message displayed under the class name:
Model class has not been generated yet.
- To solve this, I used the following command in a Terminal:
$ cd Sources/MyPackage
$ xcrun coremlcompiler generate MyModel.mlmodel --language Swift .
This generated a MyModel.swift
file next to the mlmodel file.
- I plugged the model in the code
MyPackage.swift
:
import CoreML
@available(iOS 12.0, *)
struct MyPackage {
var model = try! MyModel(configuration: MLModelConfiguration())
}
- Finally, in the test file
MyPackageTests.swift
, I create an instance of MyPackage:
import XCTest
@testable import MyPackage
final class MyPackageTests: XCTestCase {
func testExample() {
if #available(iOS 12.0, *) {
let foo = MyPackage()
} else {
// Fallback on earlier versions
}
}
static var allTests = [
("testExample", testExample),
]
}
I get the following error (it seems that the CoreML model was not found):
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
I must have missed something... I hope my description was clear and detailed enough. Thank you for your help!
This line is probably where it goes wrong:
var model = try! MyModel(configuration: MLModelConfiguration())
Since you've added a mlmodel file to the package, it hasn't been compiled yet. I'm not an expert on Swift packages, but I don't believe Xcode automatically compiles this model now. You can see this for yourself when you open up the compiled app bundle -- does it have the mlmodel file in it or the mlmodelc folder?
You may need to add the mlmodelc to the package, not the mlmodel. You can create this by doing:
Next, in your app you will need to load the model as follows:
where
YourBundle
is a reference to the bundle that contains the mlmodelc file (which I guess is the bundle for the Swift package).