🙌
FlutterAppをiOS Frameworkビルドして別プロジェクトにSPMで導入する
タイトルの通りです
FlutterアプリをネイティブのiOSで表示したかった。
cocoapods ではなく今は SwiftPackageManager が主流なのでそちらを利用する。
つまり 『Add-to-app』 を別パッケージに対して行おう。ということです。
環境: Flutter v3.13.6
ネイティブアプリで参照するまでのやり方
iOSFramework作成 -> Github Release Assets にアップロード -> Package.swift 作成
1. Flutterアプリを作成する
flutter create -i swift spm_practice_app
cd spm_practice_app
独自のパッケージ参照が必要ならこれに導入する
2. iOS Framework を作成する
# iOSのビルド周りを整備するために一応やっておく
flutter precache --ios
# iOS Framework を作成.
# Build Configuration が全てつくられてしまうので今回はReleaseのみ
flutter build ios-framework --no-debug --no-profile
# つくられたか確認
ls build/ios/framework/Release
> App.xcframework Flutter.xcframework
# zipファイルを作成
cd build/ios/framework/Release
zip -r App.xcframework.zip App.xcframework/
zip -r Flutter.xcframework.zip Flutter.xcframework/
# zipファイルのchecksum を調べて覚えておく
swift package compute-checksum App.xcframework.zip
> xxxxx
swift package compute-checksum Flutter.xcframework.zip
> yyyyy
3. Githubでリリースする
作成した .xcframework をリリースに載せる.
Private Repository でもOK
4. Package.swift を作成してGithubにPushする
AppPackage, {owner}, {repo}, {tag} は適宜置き換えてください.
Package.swift はリポジトリのルートに置いておくと楽
// swift-tools-version:5.9
import PackageDescription
let package = Package(
name: "AppPackage",
platforms: [.iOS(.v14)],
products: [
.library(
name: "AppPackage",
targets: ["App", "Flutter"]
)
],
targets: [
.binaryTarget(
name: "App",
url: "https://github.com/{owner}/{repo}/releases/download/{tag}/App.xcframework.zip",
checksum: "xxxxx"
),
.binaryTarget(
name: "Flutter",
url: "https://github.com/{owner}/{repo}/releases/download/{tag}/Flutter.xcframework.zip",
checksum: "yyyyy"
)
],
swiftLanguageVersions: [.v5]
)
5. iOSネイティブアプリにSPMでPackage.swiftがあるリポジトリを参照させる
Package.swift の name で指定した名前が表示されていればOK
Frameworkの参照を追加
Flutterの画面を呼んでみよう
1. Import できるか確認
これでビルドしてみましょう。
// AppDelegate
import UIKit
import Flutter
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var flutterEngine: FlutterEngine?
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
self.flutterEngine = FlutterEngine(name: "Practice Flutter Engine")
self.flutterEngine?.run()
return true
}
}
2. 画面を呼ぶ
UIKit+Storyboardで失礼します
import UIKit
import Flutter
class MainViewController: UIViewController {
@IBAction func onTap(_ sender: Any) {
if let app = UIApplication.shared.delegate as? AppDelegate,
let flutterEngine = app.flutterEngine {
let vc = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
present(vc, animated: true)
}
}
}
ボタンを押したら表示されて終わり.
Discussion