人总要爱着什么,活着才有意义。
如果你是Android转iOS,或者是想开发Flutter插件,可以看看我的文章:iOS 入门开发踩坑实录。我就是一个Android开发,由于开发插件需要,学了部分的iOS开发的东西。
注意对比下我的环境和你的环境是否一样,有些问题在Flutter的新版本中已经被修复了。
➜ app git:(master) ✗ flutter --version
Flutter 1.9.1+hotfix.6 • channel stable • https://github.com/flutter/flutter.git
Framework • revision cc949a8e8b (3 weeks ago) • 2019-09-27 15:04:59 -0700
Engine • revision b863200c37
Tools • Dart 2.5.0
➜ app git:(master) ✗ flutter doctor -v
[✓] Flutter (Channel stable, v1.9.1+hotfix.4, on Mac OS X 10.15 19A583, locale en-CN)
• Flutter version 1.9.1+hotfix.4 at /Users/.../flutter
• Framework revision cc949a8e8b (3 weeks ago), 2019-09-27 15:04:59 -0700
• Engine revision b863200c37
• Dart version 2.5.0
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
• Android SDK at /Users/notzuonotdied/Library/Android/sdk
• Android NDK location not configured (optional; useful for native profiling support)
• Platform android-29, build-tools 29.0.2
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 11.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 11.1, Build version 11A1027
• CocoaPods version 1.8.3
[✓] Android Studio (version 3.5)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 40.1.2
• Dart plugin version 191.8423
• Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
[!] IntelliJ IDEA Ultimate Edition (version 2019.2.3)
• IntelliJ at /Applications/IntelliJ IDEA.app
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
• For information about installing plugins, see
https://flutter.dev/intellij-setup/#installing-the-plugins
[✓] VS Code (version 1.39.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.5.1
[✓] Connected device (1 available)
• iPhone 11 Pro Max • 61AA9D21-B994-4FC5-9164-757EABF90190 • ios • com.apple.CoreSimulator.SimRuntime.iOS-13-1 (simulator)
! Doctor found issues in 1 category.
本章节用于探讨Flutter编译产物以及其集成方式。
首先,先看看混编Flutter的目录结构,主要包含了三个部分:
➜ temp tree -L 2
.
├── Android # Android工程
├── flutter_module
│ ├── README.md
│ ├── flutter_module.iml
│ ├── flutter_module_android.iml
│ ├── lib # Flutter源码目录
│ ├── pubspec.yaml # Flutter依赖
│ └── test
└── iOS # iOS工程
├── Podfile
├── Podfile.lock
├── Pods
├── iOS
├── iOS.xcodeproj
└── iOS.xcworkspace
9 directories, 9 files
看看编译之后会生成什么产物?
先看看flutter_module
目录的层级结构:
➜ flutter_module tree
.
├── README.md
├── flutter_module.iml
├── flutter_module_android.iml
├── lib # Flutter源码
│ └── main.dart
├── pubspec.lock
├── pubspec.yaml # 依赖
└── test
└── widget_test.dart
2 directories, 10 files
当我们执行Flutter build ios
会发生什么?
➜ flutter_module flutter build ios
Building com.wtfexample.flutterModule for device (ios-release)...
Found saved certificate choice "Apple Development: [email protected] (xxxxxxxx)". To clear, use
"flutter config".
Signing iOS app for device deployment using developer identity: "Apple Development:
[email protected] (xxxxxxxx)"
Running Xcode build...
├─Building Dart code... 20.0s
├─Generating dSYM file... 0.3s
├─Stripping debug symbols... 0.0s
├─Assembling Flutter resources... 0.7s
└─Compiling, linking and signing... 3.9s
Xcode build done. 29.6s
Built /Users/.../flutter_module/build/ios/iphoneos/Runner.app.
让我们来看看目录结构:
➜ flutter_module tree -da -L 2
.
├── .android # Android编译产物
│ ├── Flutter
│ ├── app
│ └── gradle
├── .idea
│ └── libraries
├── .ios # iOS编译产物
│ ├── Config
│ ├── Flutter
│ ├── Frameworks
│ ├── Pods
│ ├── Runner
│ ├── Runner.xcodeproj
│ └── Runner.xcworkspace
├── build
│ ├── aot
│ ├── dSYMs.noindex
│ └── ios
├── lib
└── test
- 主要是多了以下的部分:
```shell
.
├── .android # Android编译产物
├── .ios # iOS编译产物
├── build
│ ├── aot
│ ├── dSYMs.noindex
│ └── ios
这些也是我们要分析的内容啦,╮(╯▽╰)╭
➜ .ios tree Config
Config
├── Debug.xcconfig
├── Flutter.xcconfig
└── Release.xcconfig
0 directories, 3 files
➜ Config cat Debug.xcconfig
#include "Flutter.xcconfig"
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
➜ Config cat Release.xcconfig
#include "Flutter.xcconfig"
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
➜ Config cat Flutter.xcconfig
#include "../Flutter/Generated.xcconfig"
ENABLE_BITCODE=NO # 目前Flutter不支持BitCode模式,默认关闭
值得一提的是Flutter.xcconfig
依赖了Flutter/Generated.xcconfig
,这个文件详见下面章节的分析。Flutter/Generated.xcconfig
配置了一些Flutter Module工程的关键环境变量。
➜ Flutter tree -da -L 2
.
├── .symlinks # 这是Flutter Module依赖的插件的路径,都是使用了Soft Link
│ ├── amap_location -> /Users/.../amap_location-0.2.0
│ ├── flutter_alipay -> /Users/.../flutter_alipay-0.1.2
│ ├── flutter_amap -> /Users/.../flutter_amap-0.0.1
│ ├── flutter_easy_nfc -> /Users/.../flutter_easy_nfc-0.0.1
│ ├── flutter_statusbar -> /Users/.../flutter_statusbar-0.0.1
│ ├── flutter_wechat_ble -> /Users/.../flutter_wechat_ble-0.1.4
│ ├── linker -> /Users/.../linker-0.0.2
│ └── mmkv_flutter -> /Users/.../mmkv_flutter-1.0.10
├── App.framework # Flutter业务代码
│ └── flutter_assets # Flutter依赖的静态资源,如字体、图片等。
├── FlutterPluginRegistrant
│ └── Classes
└── engine # Flutter引擎,默认从$FlutterHome/bin/cache/artifacts复制一份。
└── Flutter.framework
15 directories
这是Flutter Module依赖的插件的路径,都是使用了Soft Link。
➜ .symlinks tree
.
├── amap_location -> /Users/.../amap_location-0.2.0
├── flutter_alipay -> /Users/.../flutter_alipay-0.1.2
├── flutter_amap -> /Users/.../flutter_amap-0.0.1
├── flutter_easy_nfc -> /Users/.../flutter_easy_nfc-0.0.1
├── flutter_statusbar -> /Users/.../flutter_statusbar-0.0.1
├── flutter_wechat_ble -> /Users/.../flutter_wechat_ble-0.1.4
├── linker -> /Users/.../linker-0.0.2
└── mmkv_flutter -> /Users/.../mmkv_flutter-1.0.10
8 directories, 0 files
Flutter业务层代码,以及一些静态资源文件。
我们可以看看flutter_assets
到底有什么东西?
➜ App.framework git:(master) ✗ tree -a -L 2
.
├── App
├── Info.plist
└── flutter_assets
├── AssetManifest.json
├── FontManifest.json
├── LICENSE
├── animations # 动画
├── assets
├── fonts # 字体
├── images # 图片
└── packages # packages中的一些资源
6 directories, 5 files
Flutter业务层代码编译产物App.framework的一些信息,诸如版本信息、BundleId、版本号等等。
Flutter注册制,自动注册各个依赖的Flutter插件。
➜ FlutterPluginRegistrant tree -a -L 2
.
├── Classes
│ ├── GeneratedPluginRegistrant.h
│ └── GeneratedPluginRegistrant.m
└── FlutterPluginRegistrant.podspec
1 directory, 3 files
如下所示:
➜ FlutterPluginRegistrant cat Classes/GeneratedPluginRegistrant.m
//
// Generated file. Do not edit.
//
#import "GeneratedPluginRegistrant.h"
#import
#import
#import
#import
#import
#import
#import
#import
@implementation GeneratedPluginRegistrant
+ (void)registerWithRegistry:(NSObject*)registry {
[AmapLocationPlugin registerWithRegistrar:[registry registrarForPlugin:@"AmapLocationPlugin"]];
[FlutterAlipayPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterAlipayPlugin"]];
[FlutterAmapPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterAmapPlugin"]];
[FlutterEasyNfcPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterEasyNfcPlugin"]];
[FlutterStatusbarPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterStatusbarPlugin"]];
[FlutterWechatBlePlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterWechatBlePlugin"]];
[LinkerPlugin registerWithRegistrar:[registry registrarForPlugin:@"LinkerPlugin"]];
[MmkvFlutterPlugin registerWithRegistrar:[registry registrarForPlugin:@"MmkvFlutterPlugin"]];
}
@end
这个是Flutter编译的时候自动生成的,定义了一些关键的配置。
➜ Flutter cat Generated.xcconfig
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/Users/.../1.9.1+hotfix.6-stable
FLUTTER_APPLICATION_PATH=/Users/.../flutter_module
FLUTTER_TARGET=lib/main.dart
FLUTTER_BUILD_DIR=build
SYMROOT=${SOURCE_ROOT}/../build/ios
FLUTTER_BUILD_NAME=1.0.0
FLUTTER_BUILD_NUMBER=1
这个和Flutter/Generated.xcconfig
一样是Flutter编译生成的,用于初始化一些必须的变量。
➜ Flutter cat flutter_export_environment.sh
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/.../1.9.1+hotfix.6-stable"
export "FLUTTER_APPLICATION_PATH=/Users/.../flutter_module"
export "FLUTTER_TARGET=lib/main.dart"
export "FLUTTER_BUILD_DIR=build"
export "SYMROOT=${SOURCE_ROOT}/../build/ios"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
具体用处可见下面章节Flutter/podhelper.rb的install_flutter_application_pod
函数实现。
这个是直接从Flutter的SDK安装目录复制过来的,路径在$FLUTTER_ROOT/bin/cache/artifacts
。
这个是最核心的一部分,分析Flutter Module依赖的插件的依赖,
install
到Flutter的.ios
工程中。
在.ios/Podfile
中,我们看到Podfile
加载使用load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
加载了podhelper.rb
这个脚本。
➜ .ios git:(master) ✗ cat Podfile
platform :ios, '8.0'
# Flutter Module的目录
flutter_application_path = '../'
# 这里的podhelper.rb就是.ios/Flutter/podhelper.rb
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
# install依赖
target 'Runner' do
# 函数,定义在podhelper.rb
install_flutter_engine_pod
# 函数,定义在podhelper.rb
install_flutter_plugin_pods flutter_application_path
end
# 在pod install的最后一步,执行某些配置
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO' # Flutter默认不支持BitCode
end
end
end
# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
install! 'cocoapods', :disable_input_output_paths => true
这个脚本其实就如下图所示的流程。
下面,我们来分析下Flutter/podhelper.rb
:
这个是一个入口函数,包含了几个函数:
# Install pods needed to embed Flutter application, Flutter engine, and plugins
# from the host application Podfile.
#
# @example
# target 'MyApp' do
# install_all_flutter_pods 'my_flutter'
# end
# @param [String] flutter_application_path Path of the root directory of the Flutter module.
# Optional, defaults to two levels up from the directory of this script.
# MyApp/my_flutter/.ios/Flutter/../..
def install_all_flutter_pods(flutter_application_path = nil)
# 跳两级出去,即Flutter工程根目录
flutter_application_path ||= File.join('..', '..')
# 添加Flutter Engine依赖
install_flutter_engine_pod
# 添加Flutter插件的依赖
install_flutter_plugin_pods(flutter_application_path)
# 添加Flutter业务代码的依赖
install_flutter_application_pod(flutter_application_path)
end
# Install Flutter engine pod.
#
# @example
# target 'MyApp' do
# install_flutter_engine_pod
# end
def install_flutter_engine_pod
# 核心工作,复制Flutter的引擎到工程目录下。
engine_dir = File.join(__dir__, 'engine')
if !File.exist?(engine_dir)
# Copy the debug engine to have something to link against if the xcode backend script has not run yet.
# CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.
debug_framework_dir = File.join(flutter_root, 'bin', 'cache', 'artifacts', 'engine', 'ios')
# 创建目录并拷贝引擎
FileUtils.mkdir_p(engine_dir)
FileUtils.cp_r(File.join(debug_framework_dir, 'Flutter.framework'), engine_dir)
FileUtils.cp(File.join(debug_framework_dir, 'Flutter.podspec'), engine_dir)
end
# Keep pod path relative so it can be checked into Podfile.lock.
# Process will be run from project directory.
engine_pathname = Pathname.new engine_dir
project_directory_pathname = Pathname.new Dir.pwd
relative = engine_pathname.relative_path_from project_directory_pathname
pod 'Flutter', :path => relative.to_s, :inhibit_warnings => true
end
debug_framework_dir = File.join(flutter_root, 'bin', 'cache', 'artifacts', 'engine', 'ios')
指向的目录是Flutter引擎的目录,可以看看$FlutterRoot/bin/cache/artifacts/engine
这个目录:
➜ 1.9.1+hotfix.6-stable git:(stable) ✗ tree bin/cache/artifacts/engine -L 1 | grep ios
├── ios
│ ├── Flutter.framework
│ ├── Flutter.framework.zip
│ ├── Flutter.podspec
│ ├── LICENSE
│ ├── gen_snapshot_arm64
│ └── gen_snapshot_armv7
├── ios-profile
│ ├── Flutter.framework
│ ├── Flutter.framework.zip
│ ├── Flutter.podspec
│ ├── LICENSE
│ ├── gen_snapshot_arm64
│ └── gen_snapshot_armv7
└── ios-release
├── Flutter.framework
├── Flutter.framework.zip
├── Flutter.podspec
├── LICENSE
├── gen_snapshot_arm64
└── gen_snapshot_armv7
# Install Flutter plugin pods.
#
# @example
# target 'MyApp' do
# install_flutter_plugin_pods 'my_flutter'
# end
# @param [String] flutter_application_path Path of the root directory of the Flutter module.
# Optional, defaults to two levels up from the directory of this script.
# MyApp/my_flutter/.ios/Flutter/../..
def install_flutter_plugin_pods(flutter_application_path)
# 核心工作,增加Flutter插件注册FlutterPluginRegistrant库(自动生成并注册Flutter Channel)
# 分析插件的依赖并创建插件的依赖的软链接到.symlinks目录下。
flutter_application_path ||= File.join('..', '..')
# Keep pod path relative so it can be checked into Podfile.lock.
# Process will be run from project directory.
current_directory_pathname = Pathname.new __dir__
project_directory_pathname = Pathname.new Dir.pwd
relative = current_directory_pathname.relative_path_from project_directory_pathname
pod 'FlutterPluginRegistrant', :path => File.join(relative, 'FlutterPluginRegistrant'), :inhibit_warnings => true
symlinks_dir = File.join(relative, '.symlinks')
FileUtils.mkdir_p(symlinks_dir)
plugin_pods = parse_KV_file(File.join(flutter_application_path, '.flutter-plugins'))
plugin_pods.map do |r|
symlink = File.join(symlinks_dir, r[:name])
FileUtils.rm_f(symlink)
File.symlink(r[:path], symlink)
pod r[:name], :path => File.join(symlink, 'ios'), :inhibit_warnings => true
end
end
FlutterPluginRegistrant
这个的生成可见Flutter xcode_backend分析,我们先看看.flutter-plugins
:➜ flutter_module cat .flutter-plugins
amap_location=/.../1.9.1+hotfix.6-stable/.pub-cache/.../amap_location-0.2.0/
flutter_alipay=/.../1.9.1+hotfix.6-stable/.pub-cache/.../flutter_alipay-0.1.2/
flutter_amap=/.../1.9.1+hotfix.6-stable/.pub-cache/.../flutter_amap-0.0.1/
flutter_easy_nfc=/.../1.9.1+hotfix.6-stable/.pub-cache/.../flutter_easy_nfc-0.0.1/
flutter_statusbar=/.../1.9.1+hotfix.6-stable/.pub-cache/.../flutter_statusbar-0.0.1/
flutter_wechat_ble=/.../1.9.1+hotfix.6-stable/.pub-cache/.../flutter_wechat_ble-0.1.4/
linker=/.../1.9.1+hotfix.6-stable/.pub-cache/.../linker-0.0.2/
mmkv_flutter=/.../1.9.1+hotfix.6-stable/.pub-cache/.../mmkv_flutter-1.0.10/
由此可见,这里保存了Flutter工程依赖的插件的本地缓存目录。
# Install Flutter application pod.
#
# @example
# target 'MyApp' do
# install_flutter_application_pod '../flutter_settings_repository'
# end
# @param [String] flutter_application_path Path of the root directory of the Flutter module.
# Optional, defaults to two levels up from the directory of this script.
# MyApp/my_flutter/.ios/Flutter/../..
def install_flutter_application_pod(flutter_application_path)
# 编译Flutter的业务层代码并依赖到主工程。
app_framework_dir = File.join(__dir__, 'App.framework')
app_framework_dylib = File.join(app_framework_dir, 'App')
if !File.exist?(app_framework_dylib)
# Fake an App.framework to have something to link against if the xcode backend script has not run yet.
# CocoaPods will not embed the framework on pod install (before any build phases can run) if the dylib does not exist.
# Create a dummy dylib.
FileUtils.mkdir_p(app_framework_dir)
`echo "static const int Moo = 88;" | xcrun clang -x c -dynamiclib -o "#{
app_framework_dylib}" -`
end
# Keep pod and script phase paths relative so they can be checked into source control.
# Process will be run from project directory.
current_directory_pathname = Pathname.new __dir__
project_directory_pathname = Pathname.new Dir.pwd
relative = current_directory_pathname.relative_path_from project_directory_pathname
pod 'flutter_app', :path => relative.to_s, :inhibit_warnings => true
# 读取flutter_export_environment.sh,并提供必要的环境变量
flutter_export_environment_path = File.join('${SRCROOT}', relative, 'flutter_export_environment.sh');
# 最关键的一步,涉及到了xcode_backend.sh。
script_phase :name => 'Run Flutter Build Script',
:script => "set -e\nset -u\nsource \"#{
flutter_export_environment_path}\"\n\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/xcode_backend.sh build",
:input_files => [
File.join('${SRCROOT}', flutter_application_path, '.metadata'),
File.join('${SRCROOT}', relative, 'App.framework', 'App'),
File.join('${SRCROOT}', relative, 'engine', 'Flutter.framework', 'Flutter'),
flutter_export_environment_path
],
:execution_position => :before_compile
end
"$FLUTTER_ROOT\"/packages/flutter_tools/bin/xcode_backend.sh
看看File.join('${SRCROOT}', flutter_application_path, '.metadata'),
这里的'.metadata'
:
➜ flutter_module ✗ cat .metadata
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b
channel: stable
project_type: module
这里存放的是工程依赖的Flutter tool版本。
# 分析Generated.xcconfig等配置文件
def parse_KV_file(file, separator='=')
file_abs_path = File.expand_path(file)
if !File.exists? file_abs_path
return [];
end
pods_array = []
skip_line_start_symbols = ["#", "/"]
File.foreach(file_abs_path) {
|line|
next if skip_line_start_symbols.any? {
|symbol| line =~ /^\s*#{symbol}/ }
plugin = line.split(pattern=separator)
if plugin.length == 2
podname = plugin[0].strip()
path = plugin[1].strip()
podpath = File.expand_path("#{
path}", file_abs_path)
pods_array.push({
:name => podname, :path => podpath});
else
puts "Invalid plugin specification: #{
line}"
end
}
return pods_array
end
# 分析Generated.xcconfig找到FLUTTER_ROOT地址
# FLUTTER_ROOT指的是Flutter SDK的路径
def flutter_root
generated_xcode_build_settings = parse_KV_file(File.join(__dir__, 'Generated.xcconfig'))
if generated_xcode_build_settings.empty?
puts "Generated.xcconfig must exist. Make sure `flutter pub get` is executed in the Flutter module."
exit
end
generated_xcode_build_settings.map {
|p|
if p[:name] == 'FLUTTER_ROOT'
return p[:path]
end
}
end
函数 | 作用 |
---|---|
install_all_flutter_pods |
入口函数,跳转到Flutter工程根目录,添加Flutter Engine依赖、Flutter插件依赖、Flutter业务层代码依赖。 |
install_flutter_engine_pod |
复制Flutter Debug版本的引擎到工程目录下,位于.ios/Flutter 。 |
install_flutter_plugin_pods |
生成Flutter插件的注册库并依赖,分析各个Flutter插件的依赖,并创建依赖库的软链接到.symlinks 目录下,即注册插件、分析依赖并依赖到主工程。 |
install_flutter_application_pod |
编译Flutter 业务层代码到App.framework,并依赖到主工程。 |
parse_KV_file |
分析Generated.xcconfig 等配置文件,用于插件依赖分析。 |
flutter_root |
分析Generated.xcconfig 找到FLUTTER_ROOT 地址,FLUTTER_ROOT 指的是Flutter SDK的路径。 |
这个目录存放的是Flutter插件依赖的库。
➜ .ios tree -L 1 Pods
Pods
├── AMap3DMap
├── AMapFoundation
├── AMapLocation
├── AliPay
├── Headers # 头文件*.h
├── Local\ Podspecs # Flutter插件的PodSpec
├── MMKV
├── Manifest.lock # 即Podfile.lock,保存了依赖的版本和地址等信息
├── Pods.xcodeproj
└── Target\ Support\ Files # 存放Flutter插件依赖的库的一些配置文件
9 directories, 1 file
分为Private
和Public
分别存放依赖库的头文件。
➜ .ios tree -L 2 Pods/Headers
Pods/Headers
├── Private
│ ├── FlutterPluginRegistrant
│ ├── MMKV
│ ├── amap_location
│ ├── flutter_alipay
│ ├── flutter_amap
│ ├── flutter_easy_nfc
│ ├── flutter_statusbar
│ ├── flutter_wechat_ble
│ ├── linker
│ └── mmkv_flutter
└── Public
├── FlutterPluginRegistrant
├── MMKV
├── amap_location
├── flutter_alipay
├── flutter_amap
├── flutter_easy_nfc
├── flutter_statusbar
├── flutter_wechat_ble
├── linker
└── mmkv_flutter
22 directories, 0 files
在Flutter工程中,直接在pubspec.yaml依赖了插件,在执行flutter build ios
的时候,就会执行flutter pub get
和flutter package get
,将Flutter插件下载到本地,最后Flutter插件的podspec会被自动转换为podspec.json,并存放在.ios/Pods/Local Podspecs
中。
➜ .ios tree -L 1 Pods/Local\ Podspecs
Pods/Local\ Podspecs
├── Flutter.podspec.json
├── FlutterPluginRegistrant.podspec.json
├── amap_location.podspec.json
├── flutter_alipay.podspec.json
├── flutter_amap.podspec.json
├── flutter_easy_nfc.podspec.json
├── flutter_statusbar.podspec.json
├── flutter_wechat_ble.podspec.json
├── linker.podspec.json
└── mmkv_flutter.podspec.json
0 directories, 10 files
存放Flutter插件依赖的库的一些配置文件。
➜ .ios tree -L 1 Pods/Target\ Support\ Files
Pods/Target\ Support\ Files
├── AMap3DMap
├── AMapFoundation
├── AMapLocation
├── AliPay
├── Flutter
├── FlutterPluginRegistrant
├── MMKV
├── Pods-Runner
├── amap_location
├── flutter_alipay
├── flutter_amap
├── flutter_easy_nfc
├── flutter_statusbar
├── flutter_wechat_ble
├── linker
└── mmkv_flutter
16 directories, 0 files
flutter build ios --release
后的一些关键编译产物为:
产物 | 介绍 |
---|---|
App.framework | Dart业务源码相关文件,在Debug模式下就是一个很小的空壳,在Release模式下包含全部业务逻辑。 |
flutter_assets | Flutter依赖的静态资源,如字体、图片等。 在Flutter 1.9.1这种已经被合并进App.framework。 |
FlutterPluginRegistrant | Flutter插件注册制,自动注册Flutter插件。 |
Flutter.framework | Flutter库和引擎。 |
.symlinks | 指向Flutter插件依赖库的实际地址。 |
因此,实际上Native接入Flutter的需要的就是接入以上的产物,其中flutter build ios
生成的产物Generated.xcconfig、flutter_export_environment.sh为编译提供了必要的参数。