This project is a sample of how to add Flutter to existing app. For while is to iOS app only.
It uses "Add-to-App" Flutter feature. We will use Flutter module. This feature is available, while for now (Flutter 1.9), at Flutter master channel, you should run:
$ flutter channel master
Let's assume you have an existent iOS App at swift_flutter/SwiftFlutter
, and that you want you Flutter project as a sibling:
$ flutter create -t module --org com.example flutter_module
This creates a some/path/swift_flutter/SwiftFlutter
Flutter module project with some Dart code to get you started and a .android/
hidden sub-folder that wraps up the module project in an Android library. And also, a .ios
hidden sub-folder that wraps up the module project that contains some Cocoapods and a helper Ruby script.
The description below assumes that your existing iOS app has a structure similar. If your existing app has a different folder structure and/or existing .xcconfig files, you can reuse those, but probably need to adjust some of the relative paths mentioned below accordingly.
The assumed folder structure is as follows:
some/path/swift_flutter
flutter_module/
lib/main.dart
.ios/
...
SwiftFlutter/
SwiftFlutter/
AppDelegate.swift
...
Integrating the Flutter framework requires use of the CocoaPods dependency manager. This is because the Flutter framework needs to be available also to any Flutter plugins that you might include in flutter_module
.
Add the following lines to your Podfile
:
flutter_application_path = 'path/to/flutter_module/'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
For each XCode target that needs to embed Flutter, call install_all_flutter_pods(flutter_application_path)
.
target 'SwiftFlutter' do
install_all_flutter_pods(flutter_application_path)
end
target 'SwiftFlutterTests' do
install_all_flutter_pods(flutter_application_path)
end
Whenever you change the Flutter plugin dependencies in some/path/flutter_module/pubspec.yaml
, you need to run flutter packages get
from some/path/flutter_module
to refresh the list of plugins read by the podhelper.rb
script. Then run pod install
again from some/path/SwiftFlutter
.
The podhelper.rb
script will ensure that your plugins, the Flutter.framework
, and the App.framework
are embedded in your project.
You should now be able to build the project using โB
.
The proper place to do this will be specific to your host app. Here is an example that makes sense for the blank screen of the host app generated by XCode 10.0.
First declare your app delegate to be a subclass of FlutterAppDelegate
. Then define a FlutterEngine
property, which help you to register a plugin without a FlutterViewController
instance.
In your AppDelegate.swift
:
import UIKit
import Flutter
import FlutterPluginRegistrant // Only if you have Flutter Plugins.
@UIApplicationMain
class AppDelegate: FlutterAppDelegate {
var flutterEngine : FlutterEngine?;
// Only if you have Flutter plugins.
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.flutterEngine = FlutterEngine(name: "io.flutter", project: nil);
self.flutterEngine?.run(withEntrypoint: nil);
GeneratedPluginRegistrant.register(with: self.flutterEngine);
return super.application(application, didFinishLaunchingWithOptions: launchOptions);
}
}
In your ViewController.swift
:
import UIKit
import Flutter
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(type:UIButton.ButtonType.custom)
button.addTarget(self, action: #selector(handleButtonAction), for: .touchUpInside)
button.setTitle("Press me", for: UIControl.State.normal)
button.frame = CGRect(x: 80.0, y: 210.0, width: 160.0, height: 40.0)
button.backgroundColor = UIColor.blue
self.view.addSubview(button)
}
@objc func handleButtonAction() {
let flutterEngine = (UIApplication.shared.delegate as? AppDelegate)?.flutterEngine;
let flutterViewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)!;
self.present(flutterViewController, animated: false, completion: nil)
}
}
You should now be able to build and launch SwiftFlutter on the Simulator or on a device. Pressing the button should bring up a full-screen Flutter view with the standard Flutter Demo counting app.