Flutter was not designed to be developed in combination with other platforms. It was designed to be a complete cross-platform application. However, in actual development, it is not realistic for the original project to completely use Flutter for reconstruction. For the original project, we are more likely to adopt a mixed development method. The Flutter Module can be added to iOS projects as frameworks.

1. Create a Flutter Module

Create the Flutter Module by running the following command:

CD ios project root directory flutter create --template module my_flutterCopy the code

After the Flutter module is executed, it will be created in the ios project /my_flutter directory.

Ios is a hidden directory. You can run the Flutter Module separately to test its functionality. Ios code is added to existing application projects or plug-ins, not to the module’s.ios/directory.

Because the. Ios/directory is automatically generated, do not source control it. Before building modules on a new machine, run the flutter pub get in the my_flutter directory to regenerate the.ios/directory, and then use the Flutter module to build ios projects.

2. Modules are embedded in existing applications

There are two ways to embed the Flutter module into an existing iOS application:

  • 2.1. Use CocoaPods and the installed Flutter SDK (recommended).
  • 2.2. Create Frameworks for the Flutter engine, compiled Dart code, and all Flutter plug-ins. Embed frameworks manually and update the build Settings for the existing application in Xcode.

2.1 Use CocoaPods and the installed Flutter SDK

This method requires all relevant developers to install the Flutter environment.

Modify the Podfile file in the iOS app, or create it manually if not:

# Uncomment the next line to define a global platform for your project # platform :ios, Flutter_application_path = '.. /my_flutter' load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb') target 'My App' do use_frameworks! Install the Flutter module install_all_FLutter_PODS (Flutter_APPLICation_path) endCopy the code

Run the pod install command:

When changing the dependencies of a Flutter plugin in my_flutter/pubspec.yaml or running it for the first time, run the Flutter pub get in the Flutter module directory to refresh the list of plug-ins read by the Podhelper.rb script. Then, run pod Install again from the application directory.

The PodHelper.rb script emashes the plug-ins Flutter. Framework and App. Framework into the project.

Open My app.xcworkspace with Xcode, close and reopen if open, use ⌘B to compile the project.

Embed the Flutter Frameworks in Xcode

Generate the necessary Frameworks by command and embed them into the application by manually editing the existing Xcode project. You can use this method if your team members cannot install the Flutter SDK and CocoaPods locally, or if you do not want To use CocoaPods as a dependency manager in existing applications. Flutter Build ios must be run every time a code change is made in the Flutter module.

Run the following command to generate Frameworks:

flutter build ios-framework --output=./Flutter/

Copy the code

After execution, generate relevant compilation products in the corresponding directory:

Frameworks have been generated. There are many ways to link frameworks to an iOS application. Here is one.

willApp.framework 和 Flutter.frameworkintoBuild Settings > Build Phases > Link Binary With Libraries:

Add the Frameworks directory to the left of the project:

Add ${PODS_ROOT}/.. in Build Settings -> Search Paths -> Framework Search Paths. /my_flutter/Flutter/Release

⌘B was used to compile the project, and the compilation was successful.

3. Create FlutterEngine and FlutterViewController

Embedding a Flutter page into an iOS application requires creating a FlutterEngine (the Flutter engine) and a FlutterViewController. The FlutterEngine is the host of the Dart VM and the Flutter runtime. The FlutterViewController is attached to the FlutterEngine to communicate and display the Flutter UI.

Create FlutterEngine:

import UIKit import Flutter @UIApplicationMain class AppDelegate: Lazy var flutterEngine = flutterEngine (name: flutterEngine) "my flutter engine") override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {// 2. Start flutter engine flutterengine.run (); return super.application(application, didFinishLaunchingWithOptions: launchOptions); }}Copy the code

Add a button to jump to the Flutter page:

import UIKit import Flutter class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. let button = UIButton(type: UIButton.ButtonType.custom) button.frame = CGRect(x: 80, y: 100, width: 120, height: 45) button.addTarget(self, action: #selector(showFlutter), for: UIControl. Event. TouchUpInside) button. SetTitle (" display Flutter ", for: UIControl.State.normal) button.backgroundColor = UIColor.blue self.view.addSubview(button) } @objc func showFlutter(){ let flutterEngine = (UIApplication.shared.delegate as! AppDelegate).flutterEngine let flutterVC = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil) flutterVC.modalPresentationStyle = .fullScreen present(flutterVC, animated: true, completion: nil) } }Copy the code

The above code uses caching FlutterEngine, which is also recommended.

Another option is to use the implicit FlutterEngine. Using the implicit FlutterEngine will significantly increase the display time of the Flutter UI. This is usually not recommended. This can be useful if there is no good way to determine when to start the Dart VM and when the Flutter does not need to maintain state between view controllers.

func showFlutter() {
  let flutterViewController = FlutterViewController(project: nil, nibName: nil, bundle: nil)
  present(flutterViewController, animated: true, completion: nil)
}

Copy the code

4. Debug the Flutter module

Once you have inherited the Flutter modules into your project and run the Flutter engine or UI using the Flutter platform API, you can start building your own Android or iOS project just like normal Android or iOS

But one big advantage of Flutter is its rapid development: hot Reload.

So how do we use Hot Reload to speed up our debugging of the Flutter module?

  • In the Flutter project, use the Flutter Attach
# -d specifies which device to attach to a flutter attach --app-id com.coderwhy. ios-my-test-d 3D7A877C-B0DD-4871-8D6E-0C5263B986CDCopy the code

You can then use (r/R) to refresh in time.