哈喽,我是老刘
总是劝你们不要激进的升级,你们不听,这回又来问题了吧,这次又是苹果。
最近 iOS 26 beta1 更新后,不少 Flutter 开发者发现真机调试的 Hot Reload 直接挂了,但模拟器还能用。这到底咋回事?会不会影响正式版?我们该怎么应对?今天就来聊聊这个事儿。
发生了啥?
简单来说就是iOS 26 beta1 真机调试时,Flutter 的 Hot Reload 失效了!
模拟器不受影响 :
在 macOS 上跑 iOS 模拟器,Hot Reload 依然能用。
普通 JIT 运行不受影响 :
App 还是能跑,只是调试时不能实时更新代码了。
正式版(Release)也不受影响 :
因为 Release 模式用的是 AOT 编译,不走 JIT。
所以,目前主要影响的是真机调试体验,尤其是需要频繁改 UI 的时候,不能实时刷新,效率会降低不少。
为啥 iOS 26 不让 Hot Reload 跑了?
(1)Hot Reload 是怎么工作的?
Flutter 的 Hot Reload 依赖 JIT(即时编译),具体流程是这样的:
- 调试器(debugger)附加到 App,获取内存控制权。
- 修改内存权限:用 mprotect 把代码段从 RX(只读执行) 改成 RW(可读写)。
- 写入新代码:把修改后的 Dart 代码编译成机器码,塞进内存。
- 恢复权限:再用 mprotect 把内存改回 RX,让新代码能执行。
(2)iOS 26 封杀了这个流程
苹果在 iOS 26 beta1 里加了个限制:禁止动态修改内存的可执行权限!
以前mprotect 可以随便改 RX → RW → RX,Hot Reload 就能跑通。
现在mprotect 改权限时,系统会检查代码签名,发现是调试器在搞事情,直接 Permission Denied!
(3)苹果为啥要这么干?
主要是为了安全 :
防止恶意代码注入,有些 App 会利用调试权限动态改代码,绕过审核(比如某些外挂、作弊工具)。
强化 W^X 原则,内存要么可写(W),要么可执行(X),不能同时具备,减少漏洞攻击面。
所以,苹果不是针对 Flutter,而是针对所有滥用调试权限的行为,只是 Flutter 的 Hot Reload 刚好撞枪口上了。
我们该怎么办?
那么作为Flutter开发者的我们该怎么办呢?
(1)短期方案:先绕开限制
如果你急着开发,可以这样:
- 优先用 Android 真机调试:Android 没这个限制,Hot Reload 随便用。
- 改用 iOS 模拟器:模拟器跑在 macOS 上,不受 iOS 26 限制。
- 真机调试时多用 Hot Restart:虽然不能实时刷新,但至少比全量重新编译快一点。
(2)长期方案:等 Flutter 官方适配
Flutter 团队已经在研究替代方案了,可能的路线:
解释器模式(Interpreter Mode):不编译机器码,直接解释执行 Dart 字节码,绕过 mprotect 限制。
混合执行(Hybrid AOT + JIT):主代码用 AOT 编译,热更新部分用解释器执行(类似 shorebird 的方案)。
目前 Dart 团队已经在讨论这个事了(github.com/dart-lang/s... iOS 26 发布前会有解决方案。
总结
问题:iOS 26 beta1 封杀了 mprotect 动态改内存权限,导致 Flutter Hot Reload 在真机失效。
原因:苹果加强安全策略,防止调试权限滥用,Flutter 躺枪。
短期方案:用 Android 真机、iOS 模拟器,或者忍一忍 Hot Restart。
长期方案:等 Flutter 适配解释器或混合执行模式。
老刘的建议,说了这么多,其实别急着升级就好。
作为爱好者升级尝鲜当然没问题,但是对于正式项目来说还是要稳妥为上。
老刘做Flutter开发6年多了,Flutter大大小小这么多坑,为啥我很少踩中,还不是全靠总是苟着。
如果看到这里的同学对客户端开发或者Flutter开发感兴趣,欢迎联系老刘,我们互相学习。
点击免费领老刘整理的《Flutter开发手册》,覆盖90%应用开发场景。
可以作为Flutter学习的知识地图。
覆盖90%开发场景的《Flutter开发手册》