准备工作

本文基于Android Stuido编写,运用VSCode的同学在指令面板上能够找到大部分对应的操作

技能基础

  • Flutter(Dart)
  • iOS(Objective-C/Swift)

Flutter环境建立能够检查同目录下阿政的文章《Mac 装备 Flutter 环境》,或许Flutter中文网在MacOS上建立Flutter开发环境

IDE

  • Xcode
  • Android Studio/VSCode

其他东西

  • Flutter SDK,Android Studio需求Dart Flutter插件
  • Cocopoads

混编Flutter

  1. 创建Flutter Module

  • 运用Android Studio挑选New Flutter Project

iOS混编Flutter实战

  • 运用指令行
flutter create --template module my_flutter

更多关于flutter create 指令能够运用 flutter create --help检查,如下图:

iOS混编Flutter实战

在当时的工程目录下,能够履行flutter的指令,比如flutter run --debug 或许 flutter build ios,当然也能够运用Android Studio/IntelliJ 或许 VS Code。

Module的目录结构

my_flutter/
├── .ios/
│   ├── Runner.xcworkspace
│   └── Flutter/podhelper.rb
├── lib/
│   └── main.dart
├── test/
└── pubspec.yaml

lib/目录中编写你的Dart代码,在 my_flutter/pubspec.yaml增加Flutter依赖,包含 Flutter packages 和 plugins。

ios的工程文件隐藏在.ios文件夹中

  1. 导入Flutter Module

在iOS原生工程中导入Flutter Module有三种方法

Plan A

运用Cocoapods和Flutter SDK集成

  • podfile文件中增加下面代码:

    • # 与原生项目在同级目录的情况下
      flutter_application_path = '../my_flutter'
      load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb'
      
  • 在需求集成Flutter的target下,履行install_all_flutter_pods(flutter_application_path)

    • target 'MyApp' do
          install_all_flutter_pods(flutter_application_path)
      end
      
  • Podfilepost_install 部分,调用 flutter_post_install(installer)

    • post_install do |installer|
          flutter_post_install(installer) if defined?(flutter_post_install)
      end
      
  • 运转pod install

Plan B

在Xcode中集成frameworks。与选项3相似,仅仅需求手动办理增加到工程中,一般不引荐运用

  • 创建 frameworks,下面的示例假设你想在 some/path/MyApp/Flutter/ 目录下

    • flutter build ios-framework --output=some/path/MyApp/Flutter/
      
  • 链接到结构 能够将导出目录some/path/MyApp/Flutter/Release/ 拖到你的方针项目中,然后点击以下过程 build settings > Build Phases > Link Binary With Libraries

    • iOS混编Flutter实战
  • 内嵌结构,将导出的结构拖到‘ build settings > Build Phases > Embed Frameworks。然后从下拉菜单中挑选 “Embed & Sign”。

iOS混编Flutter实战

Plan C

运用Cocoapods在Xcode和Flutter结构中内嵌运用

  • 生成Flutter.podspec和结构

    • flutter build ios-framework --cocoapods --output=some/path/MyApp/Flutter/
      
  • 在podfile中引用

    • pod 'Flutter', :podspec => 'some/path/MyApp/Flutter/[build mode]/Flutter.podspec'
      

这边采取的是运用在同级目录的方法,当然也能够运用git办理,相关操作不再赘述。

三种方法的优缺点

第一种方法的优势在于,开发期Flutter端修改了代码,直接在原生运转程序即能看到最新的效果,但是需求本地有Flutter环境(运转Flutter doctor成功)。

后两种的方法不依赖于Flutter SDK,因为现已全部打包在了frameworks中,缺点就是麻烦,代码更新较慢,当然第二中的手动引进的方法一般是不引荐运用的。

当然能够依据各自的需求进行挑选整合。

在Apple M系列芯片机器上运转模拟器

M系列芯片的产品由于是ARM架构,模拟器也是ARM架构,虽然Flutter现已支撑arm64模拟器,但是部分插件或许没有支撑,如果运转报错相似Undefined symbols for architecture arm64的错误,请在模拟器上移除arm架构,操作如下:

iOS混编Flutter实战

原生端代码集成

在原生端集成Flutter的内容需求用到下面元素:

  • FlutterEngine
  • FlutterViewController
  • FlutterMethodChannel、FlutterBasicMessageChannel、FlutterEventChannel

代码示例:


/// 在运用前
- (void)startEngine {
    [self.flutterEngine run];
    [GeneratedPluginRegistrant registerWithRegistry:self.flutterEngine];
    /// 建立Native与Dart通讯
    [self registerMessageChannel];
}
/// Native与Dart通讯
- (void)registerMessageChannel {
    WeakifySelf();
    [self.messageChannel setMessageHandler:^(id  _Nullable message, FlutterReply  _Nonnull callback) {        /// 处理Navtive端接收到Dart通讯        [weakSelf handleMessage:message callback:callback];
    }];
}
/// Native向Flutter发送消息
- (void)sendMessage:(NSDictionary *)parameters call:(FlutterReply)callback {
    [self.messageChannel sendMessage:parameters.mj_JSONString reply:callback];
}
/// kEBGlobalFlutterEngineName、kGlobalXAppMessageChannel为常量字符串
- (FlutterEngine *)flutterEngine {
    if (!_flutterEngine) {
        _flutterEngine = [[FlutterEngine alloc] initWithName:kEBGlobalFlutterEngineName];
    }
    return _flutterEngine;
}
- (FlutterBasicMessageChannel *)messageChannel {
    if (!_messageChannel) {
        _messageChannel = [FlutterBasicMessageChannel messageChannelWithName:kGlobalXAppMessageChannel binaryMessenger:self.flutterEngine.binaryMessenger                               codec:FlutterStringCodec.sharedInstance];
    }
    return _messageChannel;
}