阅读版(HTML)· 里程碑 TestFlight 公测 · 分支 feature/pangolin-ios · 2026-06-22
这是阅读版。执行真相源是同内容的 docs/superpowers/plans/2026-06-22-ios-ipad-support.md(含 - [ ] checkbox,供 executing-plans/subagent-driven-development 驱动逐步执行)。本 HTML 仅供浏览,勾选/执行以 .md 为准。
Goal:把 iOS 隧道从「能编译的 M3 PoC 桩」推进到「iPhone/iPad 真机真正连通、扛得住 NE 内存红线、可推 TestFlight」,iPad 共用同一 iOS target 并完成布局+横屏适配。
Architecture:iOS PacketTunnel 扩展按 macOS 已验证的 libbox 集成方式重写(LibboxNewCommandServer + LibboxPlatformInterfaceProtocol + 真 utun fd),删除 PoC 的 socketpair 手工桥接;主 App 侧 VpnManager 已基本可用,仅需对齐配置 key。iPad 复用已有 form_factor.dart(宽≥600 自动走 TabletShell)。
| 项 | 值 |
|---|---|
| sing-box 版本 | v1.13.13(与节点对齐) |
| TeamID | BYL4KQHMTN |
| Bundle ID | 主 App com.pangolin.pangolinVpn / 扩展 ….PacketTunnel |
| App Group(iOS) | group.com.pangolin.pangolinVpn(非 macOS 的 <TeamID>. 前缀) |
| 扩展链接铁律 | Libbox 只 Link 不 Embed;OTHER_LDFLAGS="";otool -L 零外部 @rpath |
| libbox 铁律 | 后台队列启;非空 LibboxOverrideOptions();阻塞式 startDefaultInterfaceMonitor |
| 配置来源 | 服务端 BuildClientConfig 渲染原样下发;DNS 劫持首条规则(服务端已处理) |
| 红线词 | 用户可见文案禁 VPN/翻墙/科学上网,用「加速」口径 |
| 内存红线 | NE 进程 ~50MB(旧设备 ~15MB)— 头号风险 |
| 平台 | iOS 12+,设备族 "1,2" |
| 文件 | 责任 | 动作 |
|---|---|---|
client/ios/Frameworks/Libbox.xcframework | iOS+sim libbox 静态框架 | 构建产物放入(不入 git) |
client/ios/.gitignore | 排除框架产物 | 追加一行 |
client/ios/Runner.xcodeproj/project.pbxproj | 扩展链接、Team、OTHER_LDFLAGS | Xcode 改 |
client/ios/PacketTunnel/PacketTunnelProvider.swift | NE 扩展 libbox 集成 | 重写对齐 macOS |
client/ios/Runner/VpnManager.swift | 主 App 隧道控制 | 核对(配置 key 已是 config) |
client/ios/Runner/Info.plist | iPad orientation + 导出合规 | 改 |
client/test/responsive/form_factor_test.dart | 断点判定测试 | 新建 |
参照(只读):client/macos/PacketTunnel/PacketTunnelProvider.swift(金标准)、client/lib/core/responsive/form_factor.dart、client/lib/shell/tablet_shell.dart。
Task A1:跑 bash scripts/build-libbox.sh apple(不带 platform)→ 产出含 ios-arm64+ios-arm64_x86_64-simulator 切片的 xcframework → 拷入 client/ios/Frameworks/ → .gitignore 追加 **/Frameworks/Libbox.xcframework/。macOS 既有框架不动。
Task B1:照 macOS 扩展把 Libbox + NetworkExtension + SystemConfiguration + libresolv.tbd 只 Link 不 Embed(AppKit 换掉);扩展 OTHER_LDFLAGS="";两 target DEVELOPMENT_TEAM=BYL4KQHMTN;确认 App Groups + Network Extensions 能力。验证:flutter build ios --no-codesign 通过 + otool -L 扩展二进制零外部 @rpath。
Task C1(最大的活):现有 iOS 桩用的是真实框架里不存在的旧 API(LibboxNewService/openTun(_:)->Int32/socketpair 桥接),链入真实 Libbox 后编不过。以 macOS 金标准整体替换,仅改三处 + 接内存监控:
appGroup="group.com.pangolin.pangolinVpn"、log subsystem 改 iOS bundleresolveConfig 读 options["config"](对齐 VpnManager)+ App Group lastConfigJson 回退MemoryMonitor(start/stop/sleep/wake);handleAppMessage 仅留 getStatus/getMemoryPangolinPlatformInterface/InterfaceIterator/simpleError 原样照搬(iOS 全 API 可用)验证:flutter build ios 通过;grep 命中 后台队列 / 非空 OverrideOptions / 阻塞 interface monitor / config key 四项。
Task D1:iPhone 真机 flutter run --release → 点连接 → device console 看 startTunnel: service started、无 no available network interface/无 SIGSEGV → Safari 验出网 → 10 分钟读 peakRssBytes。
Task D2(仅当内存超限触发):本地 .srs 预取瘦身——把 geoip-cn.srs/geosite-cn.srs 打进 app bundle、启动期拷到 App Group 容器、服务端 clientconfig.go rule_set 由 remote 改 local,避免启动期下载进 NE 内存。
⚠️ TestFlight 推送以「内存实测通过」为前置闸门。
Task E1:form_factor_test.dart widget 测试锁定 iPad 竖(768)/横(1024) → tablet、iPhone(390) → mobile。
Task E2:Info.plist 开 iPad 全向 UISupportedInterfaceOrientations~ipad;iPad 模拟器逐屏竖/横目测对照 design/ui_kits/tablet 原型,无溢出/不空旷;flutter analyze 过。
Task E3:iPad 真机连通 + 横竖屏布局验收。
Task F1(用户在后台手点):注册两个 App ID(勾 App Groups + Network Extensions)、建 App Group group.com.pangolin.pangolinVpn、描述文件、App Store Connect 建 app 记录。
Task F2:Info.plist 加 ITSAppUsesNonExemptEncryption;递增构建号;flutter build ipa --release;xcrun altool/Transporter 上传 TestFlight。
otool -L 零外部 @rpath。MemoryMonitor 真机峰值 < 设备 jetsam 上限,10 分钟不被杀。执行真相源:docs/superpowers/plans/2026-06-22-ios-ipad-support.md · 设计稿:ios-ipad-support-design.html · 索引:docs/index.html