1.这里创建一个Flutter项目(App)
- 使用Xcode打开其中的iOS工程
- 打开
Generated.xcconfig
添加环境变量
//添加环境变量
//1.引擎代码的src路径
FLUTTER_ENGINE=/Users/mac/Desktop/Flutter-Engine/engine_download/src
//2.使用引擎对应版本,模拟器版本
LOCAL_ENGINE=ios_debug_sim_unopt
- Command+R运行该iOS项目
2. 工程关联过程(Xcode->Dart)
- iOS脚本配置在
Target->Build Phases->Run Script
中
/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
- 进入
$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh
($FLUTTER_ROOT
为FlutterSDK位置) xcode_backend.sh
#!/usr/bin/env bash
# Copyright 2014 The Flutter Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# exit on error, or usage of unset var
set -euo pipefail
# Needed because if it is set, cd may print the path it changed to.
unset CDPATH
function follow_links() (
cd -P "$(dirname -- "$1")"
file="$PWD/$(basename -- "$1")"
while [[ -h "$file" ]]; do
cd -P "$(dirname -- "$file")"
file="$(readlink -- "$file")"
cd -P "$(dirname -- "$file")"
file="$PWD/$(basename -- "$file")"
done
echo "$file"
)
PROG_NAME="$(follow_links "${BASH_SOURCE[0]}")"
BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
FLUTTER_ROOT="$BIN_DIR/../../.."
DART="$FLUTTER_ROOT/bin/dart"
"$DART" "$BIN_DIR/xcode_backend.dart" "$@"
-
xcode_backend.sh
没有使用到Generated.xcconfig
文件中的环境变量 - xcode工程执行了这个脚本后,然后执行到了
xcode_backend.dart
这个文件
- 进入
xcode_backend.dart
文件,之前的环境变量在这个文件使用到了。具体代码太长就没有贴出来
3.证明运行的iOS项目与我自己的渲染引擎已经关联
- 1.在运行中的项目下一个断点
touchesBegan:withEvent:
br set -n "touchesBegan:withEvent:"
- 2.点击屏幕,过掉一些UI相关的断点后,进入
FlutterViewController.mm
断点
- 3.在
touchesBegan
添加打印语句
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
NSLog(@"123");
[self dispatchTouches:touches pointerDataChangeOverride:nullptr event:event];
}
- 4.通过
Command+j
查看不到FlutterViewController.mm
文件所在位置 - 5.猜测
FlutterViewController.mm
是在Flutter引擎代码里,打开ios_debug_sim_unopt
工程查看
1.这里可以清晰的看到,刚才写的打印语句在Flutter引擎代码里面
2.此时Xcode工程和FLutter渲染引擎已经关联起来了
4.为什么点击屏幕控制台不执行打印语句?
- 原因其实很简单,当我们引擎改了代码,需要使用
ninja
去编译一次 - Xcode工程使用的是Flutter.framework,因此修改后必须编译一次更新Flutter.framework
mac@mac out % ninja -C host_debug_unopt && ninja -C ios_debug_sim_unopt
ninja: Entering directory `host_debug_unopt'
ninja: no work to do.
ninja: Entering directory `ios_debug_sim_unopt'
[16/16] STAMP obj/default.stamp
- Xcode工程停掉,再运行
- 点击模拟器屏幕,此时打印输出正常
5.原理剖析
- 此时查看
FlutterViewController.mm
文件所在位置 - 你会惊讶的发现
FlutterViewController.mm
文件不在ios_debug_sim_unopt
目录下 - 路径为
/src/flutter/shell/platform/darwin/ios/framework/Source
-
源码存放的位置并不在编译后的文件内,而是在引擎源码的其它目录下
总结 因此并不是每编译一次模拟器/真机(release/debug),就会重新生成一份源码
它是根据同一份源码编译出不同的产物
6.md5检查Flutter.framework
-
比对4次Flutter.framework的md5值(2次自定义版本,2次发布版本)
- 1.
Generated.xcconfig
添加环境变量,使用自定义引擎
mac@mac Flutter.framework % md5 Flutter
MD5 (Flutter) = 417ded8d1d0c7999c680ac31a9aae3f3
- 2.
Generated.xcconfig
注释环境变量+编译,使用发布版本引擎
mac@mac Flutter.framework % md5 Flutter
MD5 (Flutter) = 15efda2506d5e9c6904ceb1837b26124
- 3.
Generated.xcconfig
添加环境变量,使用自定义引擎
mac@mac Flutter.framework % md5 Flutter
MD5 (Flutter) = 0e4c584880f59b3b35ec48d68f820c93
- 4.
Generated.xcconfig
注释环境变量+编译,使用发布版本引擎
mac@mac Flutter.framework % md5 Flutter
MD5 (Flutter) = 6735d5613997e710ed37b9a27aab8bfc
- 可以看出,每一次的
md5值是不一样的
工程每次编译在生成Flutter.framework都是不一样的(无论是发布版本还是自定义版本)
工程在每次编译生成Flutter.framework的时候还要加入内容的,因此多次是不一样的
7.Xcode13不显示Product目录
- 打开项目
project.pbxproj
- 搜索
productRefGroup
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146E51CF9000F007C117D /* Products */;
- 将
productRefGroup
的值换成mainGroup
的(这里的我已经修改好了) - Command+s保存后退出,就会发现工程中的Product目录显示出来了