iOS + iPad 支持 实施计划

阅读版(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)。

Global Constraints(每个任务隐含包含)

sing-box 版本v1.13.13(与节点对齐)
TeamIDBYL4KQHMTN
Bundle ID主 App com.pangolin.pangolinVpn / 扩展 …​.PacketTunnel
App Group(iOS)group.com.pangolin.pangolinVpn(非 macOS 的 <TeamID>. 前缀)
扩展链接铁律Libbox 只 Link 不 EmbedOTHER_LDFLAGS=""otool -L 零外部 @rpath
libbox 铁律后台队列启;非空 LibboxOverrideOptions();阻塞式 startDefaultInterfaceMonitor
配置来源服务端 BuildClientConfig 渲染原样下发;DNS 劫持首条规则(服务端已处理)
红线词用户可见文案禁 VPN/翻墙/科学上网,用「加速」口径
内存红线NE 进程 ~50MB(旧设备 ~15MB)— 头号风险
平台iOS 12+,设备族 "1,2"

File Structure

文件责任动作
client/ios/Frameworks/Libbox.xcframeworkiOS+sim libbox 静态框架构建产物放入(不入 git)
client/ios/.gitignore排除框架产物追加一行
client/ios/Runner.xcodeproj/project.pbxproj扩展链接、Team、OTHER_LDFLAGSXcode 改
client/ios/PacketTunnel/PacketTunnelProvider.swiftNE 扩展 libbox 集成重写对齐 macOS
client/ios/Runner/VpnManager.swift主 App 隧道控制核对(配置 key 已是 config)
client/ios/Runner/Info.plistiPad orientation + 导出合规
client/test/responsive/form_factor_test.dart断点判定测试新建

参照(只读):client/macos/PacketTunnel/PacketTunnelProvider.swift(金标准)、client/lib/core/responsive/form_factor.dartclient/lib/shell/tablet_shell.dart

任务分阶段

PHASE A · libbox iOS 框架(解阻塞)

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 既有框架不动。

PHASE B · Xcode 接线与签名

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

PHASE C · iOS Provider 重写(对齐 macOS)

Task C1(最大的活):现有 iOS 桩用的是真实框架里不存在的旧 APILibboxNewService/openTun(_:)->Int32/socketpair 桥接),链入真实 Libbox 后编不过。以 macOS 金标准整体替换,仅改三处 + 接内存监控:

验证:flutter build ios 通过;grep 命中 后台队列 / 非空 OverrideOptions / 阻塞 interface monitor / config key 四项。

PHASE D · 真机连通与内存验收(含头号风险闸门)

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 由 remotelocal,避免启动期下载进 NE 内存。

⚠️ TestFlight 推送以「内存实测通过」为前置闸门。

PHASE E · iPad UI 适配(布局 + 横屏)

Task E1form_factor_test.dart widget 测试锁定 iPad 竖(768)/横(1024) → tablet、iPhone(390) → mobile。

Task E2Info.plist 开 iPad 全向 UISupportedInterfaceOrientations~ipad;iPad 模拟器逐屏竖/横目测对照 design/ui_kits/tablet 原型,无溢出/不空旷;flutter analyze 过。

Task E3:iPad 真机连通 + 横竖屏布局验收。

PHASE F · 分发到 TestFlight

Task F1(用户在后台手点):注册两个 App ID(勾 App Groups + Network Extensions)、建 App Group group.com.pangolin.pangolinVpn、描述文件、App Store Connect 建 app 记录。

Task F2Info.plistITSAppUsesNonExemptEncryption;递增构建号;flutter build ipa --releasexcrun altool/Transporter 上传 TestFlight。

验收标准(DoD)

  1. Libbox 含 iOS 切片;扩展 otool -L 零外部 @rpath
  2. iPhone 真机:连接 → sing-box 起来 → 打开境外站点。
  3. iPad 真机:连通 + 竖/横屏布局对照原型无拉伸/空旷。
  4. MemoryMonitor 真机峰值 < 设备 jetsam 上限,10 分钟不被杀。
  5. 成功 Archive 并上传 TestFlight,外部测试者可装可连。

执行真相源:docs/superpowers/plans/2026-06-22-ios-ipad-support.md · 设计稿:ios-ipad-support-design.html · 索引:docs/index.html