iOS + iPad 支持设计方案

Pangolin Flutter 客户端 · 目标里程碑 TestFlight 公测 · 分支 feature/pangolin-ios · 2026-06-22

一句话:iOS 不是从零起步,而是停在一个 “M3 PoC” 半成品上 —— Xcode 工程、Swift 源码、entitlements、iPad 布局骨架都在,唯一硬阻塞是 Libbox.xcframework 只编了 macOS 切片。本方案把 iOS 隧道从「能编译的桩」推到「真机能连通、扛得住 NE 内存红线、可上 TestFlight」,iPad 跟着 iPhone 一起好(同一个 iOS target,非单独版本)。

1. 目标与范围

维度本轮做本轮不做
连通性iPhone / iPad 真机真正连上网、出网走自有节点
分发App Store Connect 配置 + 描述文件 + TestFlight 外部测试完整 App Store 上架审核合规(隐私清单细节、审核问答)
iPad布局适配 + 横屏(宽屏主从/侧边栏,6 屏不拉伸)Split View / Stage Manager 动态重排、外接键盘/指针/拖拽
平台iOS 12+,设备族 iPhone + iPad(已是 "1,2"tvOS / visionOS

前置条件已具备:付费 Apple Developer 账号(TeamID BYL4KQHMTN),可上 App Store Connect。

2. 现状盘点(代码已有什么)

状态说明
Xcode 工程接线已有Runner + PacketTunnel 两 target 已接好;设备族 iPhone+iPad;部署目标 iOS 12
iOS Swift 源码PoC 桩PacketTunnelProvider.swift(20KB) / VpnManager.swift / MemoryMonitor.swift 在,但 Provider 未真正接通 libbox
entitlements已有正确的 iOS 格式:NE packet-tunnel-provider + App Group group.com.pangolin.pangolinVpn
Bundle ID已定主 App com.pangolin.pangolinVpn,扩展 com.pangolin.pangolinVpn.PacketTunnel
Libbox.xcframework缺 iOS 切片当前只有 macos-arm64_x86_64,缺 ios-arm64 + ios-arm64-simulator
DEVELOPMENT_TEAM未设iOS 工程未填 team(macOS 已填 BYL4KQHMTN
iPad 布局骨架shell/tablet_shell.dart + core/responsive/form_factor.dart 起步;design/ui_kits/tablet 有原型

iOS Provider 与 macOS 的差距(grep 实测)

关键修复点macOSiOS
后台队列启 libbox(防三方死锁)半(有 DispatchQueue.global,未接启动序列)
非空 LibboxOverrideOptions()(防 SIGSEGV)
阻塞式 startDefaultInterfaceMonitor
startOrReloadService 真正拉起 sing-box
DNS 劫持首条规则服务端渲染下发服务端渲染下发(同源,无需客户端改)

3. 架构决策:iOS Provider 实现策略

方案 A —— 移植成独立 iOS 版,两端各自维护 已选

仓库本就分 macos/PacketTunnelios/PacketTunnel。两端是真分叉:System Extension vs App Extension、App Group 前缀 BYL4KQHMTN. vs group.、iOS 独有 ~50MB 内存红线。接受可控重复,在 iOS Provider 文件头放一份「与 macOS 的 parity 对照」注释防漂移。

取舍:成本最低、最贴合现有结构。

方案 B(未选)—— 抽公共 Swift core 两端共享

把 interface monitor / libbox 启动序列 / 配置 IPC 抽成共享文件,平台只留差异 shim。无漂移,但要给 ios + macos 两个独立 Flutter 工程都接好跨 target 共享文件,Xcode 这块很折腾。抽象收益压不过两套工程的接线成本。

4. 五条工作线

① libbox iOS 框架(解阻塞)

② iOS Provider 对齐 macOS 修复

③ App Group / IPC

④ iPad UI 适配(布局 + 横屏)

⑤ 分发到 TestFlight

5. 头号风险:iOS NE 内存红线

iOS Network Extension 进程 ~50MB 内存硬顶(旧设备 ~15MB)× sing-box + 远程 rule-set
配置层 clientconfig.go 的国内分流走远程拉 geoip-cn.srs / geosite-cn.srs,启动期下载进内存,在 NE 进程里是 jetsam 杀进程的主因。

两道闸:

  1. 先测:用 MemoryMonitor 在真机跑满配置,拿到峰值 resident 再决定。
  2. 不够就瘦身:落 #5 TODO 的本地 .srs 预取(避免启动期下载进内存),必要时 iOS 走精简 rule-set。

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

其他风险

风险缓解
iOS Provider 移植引入新死锁/崩溃严格照 macos-sysext 排障 runbook 的铁律;真机 device console 验证
受限网络封高位端口REALITY 数据口优先走节点 443(与 iPhone/macOS 同策略)
iPad 布局漂移设计稿对照 design/ui_kits/tablet 原型;遵守 token 单源

6. 验收标准(Definition of Done)

  1. scripts/build-libbox.sh apple 产出含 iOS 切片的 xcframework,otool -L 验扩展零外部 @rpath 依赖。
  2. iPhone 真机:开关 VPN → sing-box 真正起来 → 能打开境外站点(DNS 不失败)。
  3. iPad 真机:同上连通;竖/横屏布局对照原型无拉伸/空旷。
  4. MemoryMonitor 真机峰值 < 设备 jetsam 上限(10 分钟稳定运行不被杀)。
  5. 成功 Archive 并上传 TestFlight,外部测试者可安装并连通。

7. 不做(YAGNI)


下一步:进 writing-plans 出逐步实施计划。本文档登记于 docs/index.html