点一下地图,把 iPhone 的定位传送到那里。
原生 macOS App(SwiftUI + MapKit + 系统 Liquid Glass)· 类 iAnyGo 的 iOS 虚拟定位工具 · iOS 17+ 走 RemoteXPC/DTX 隧道、默认免 sudo · 无需越狱
中文 | English
下载:⬇️ 最新安装包(Apple Silicon / arm64,ZIP)
⚠️ 合规提示:本工具修改的是设备系统级定位,仅用于自测、演示与开发调试。请勿用于作弊、绕过风控或任何违反服务条款与法律的用途。
LocPilot 把「我这台 iPhone 现在在哪」变成地图上随手一点的事:USB 连上手机,点地图任意位置,定位就过去了 —— 不需要越狱,也不需要在手机上装任何东西。
界面用系统框架(SwiftUI + MapKit,即 Apple 地图本体),定位能力交给成熟开源引擎 —— 换引擎不用动界面,改界面不用动引擎。
- 原生 macOS App:界面只有三样东西 —— 地图、右上控件簇、左下坐标读数。全面屏,控件用系统 Liquid Glass 材质。
- Python 后端(App 自动拉起,也能独立跑):定位引擎适配层,同时对外提供 HTTP/SSE API 与 CLI —— 多点路线、GPX 回放、地址搜索、历史都长在后端。
截图:Apple 地图本体、右上玻璃控件簇、左下坐标读数;落针后显示反查到的地名。
| 特性 | 说明 |
|---|---|
| 原生界面 | Apple 地图 + 系统手势(双指平移 / 捏合),与 macOS「地图」手感一致;深浅色自动跟随 |
| 点击即传送 | 唯一交互。右上控件簇 = 连接状态 / 跟随定位 / 恢复真实定位 / 缩放;⌘K 连接 · ⌘⇧K 断开 · ⌘⇧C 恢复 |
| 引擎可插拔 | pymobiledevice3(默认)· libimobiledevice(仅 iOS ≤16)· go-ios · mock,按设备与系统版本自动选择 |
| 免 sudo 隧道 | iOS 17+ 走 RemoteXPC/DTX,默认自动建立隧道、普通用户权限即可 |
| 后端 API + CLI | 与 App 共用同一个 Session:单点传送、多点路线、GPX 导入导出、速度与循环、地址搜索、历史 |
| 不依赖 Xcode | bash macos/build.sh 即可产出 LocPilot.app,只装 Command Line Tools 也行 |
技术栈:Swift 5.9 + SwiftUI + MapKit + Liquid Glass(SwiftPM:LocPilotKit / LocPilotApp)· 后端 Python ≥3.9,运行期只用标准库 · REST + SSE · 引擎 pymobiledevice3 / libimobiledevice / go-ios / mock · 地理 MapKit / OSRM / Nominatim
状态:v1.0.2 功能已全部完成,提供 Apple Silicon(M 系列)原生安装包;已知限制见 第 7 节。
主窗口只有三样东西:地图、右上控件簇、左下坐标读数。
| 控件 | 作用 |
|---|---|
| 📱 手机图标 | 连接状态:连上后绿色泛光;点击 = 连接 / 断开。悬停显示设备名 |
| ➤ 定位箭头 | 回到当前(虚拟)位置 |
| ⤴ 恢复真实定位 | 清除虚拟定位,设备回到真实 GPS |
| + / − | 放大 / 缩小(以当前可见跨度为基准) |
手势就是系统地图的手势:界面直接把 MapKit 本体当画布,只开平移与缩放两种交互 —— 触控板双指拖动平移、双指捏合缩放,惯性、回弹、缩放锚点全部由系统负责,跟 macOS「地图」App 一模一样。 这大概是整个工具体验最自然的地方:改定位不需要摇杆、不需要坐标输入框、不需要按钮面板,就是在地图上用两根手指挪一下。
快捷键:⌘K 连接 · ⌘⇧K 断开 · ⌘⇧C 恢复真实定位。
复杂功能(多点路线、GPX 回放、摇杆、历史、收藏、速度预设)保留在后端 HTTP API 与 CLI 中;原生界面刻意保持极简。
要求:Apple Silicon(M1 / M2 / M3 / M4 …)Mac + macOS 26 或更高 —— 本版以 macOS 26 SDK 构建,才能启用系统 Liquid Glass 新外观(用更低 SDK 构建会整体回落到旧版控件样式)。
-
打开 Releases,下载
LocPilot-1.0.2-arm64.zip(约 470 KB) -
解压,把 LocPilot.app 拖进「应用程序」
-
首次打开:本版为 ad-hoc 签名(未做 Apple 公证),双击会被 Gatekeeper 拦一次 —— 右键点 App →「打开」→ 弹窗里再点「打开」;或执行一次:
xattr -dr com.apple.quarantine /Applications/LocPilot.app
-
只有要改真机定位才需要装引擎:菜单栏「引擎 → 安装 / 修复定位引擎…」(约 40MB,无需 sudo)。 不装也能用内置 mock 虚拟设备把界面跑通
-
USB 连上 iPhone → 手机上点「信任此电脑」并开启开发者模式 → 点右上角手机图标连接 → 在地图上点一下,大头针落下后定位即改到那里
包完整性校验:
shasum -a 256 LocPilot-1.0.2-arm64.zip,结果应与 Release 页里的 SHA-256 一致。
# 1) 安装定位引擎(创建 .venv 并安装 pymobiledevice3;App 本体不需要)
bash scripts/setup-engine.sh
# 2) 构建原生 App(SwiftPM,命令行即可,不需要 Xcode)
bash macos/build.sh # 产物:macos/build/LocPilot.app
bash macos/build.sh --run # 构建并启动
# 3) 打开 App,点右上角手机图标连接设备,然后点地图无真机时用虚拟设备体验:
LOCPILOT_ENGINE=mock bash macos/build.sh --run构建脚本参数:--check(只做 SwiftPM 预检)· --selftest(无界面自检 JSON)· --smoke(构建 + 打包结构自检 + 启动冒烟 + 崩溃守卫)· --run · --no-build · --help。
环境变量(App 与后端都认):
| 变量 | 作用 |
|---|---|
LOCPILOT_ENGINE |
指定引擎:auto(默认)/ mock / pymobiledevice3 / libimobiledevice / go-ios |
LOCPILOT_AUTOCONNECT |
0 = 启动时不自动连接(自动化/验收用,避免误连真机) |
LOCPILOT_PYTHON |
指定 Python 解释器(默认按 App 支持目录 → 仓库 .venv → Homebrew → 系统 顺序探测) |
LOCPILOT_APP_SUPPORT |
重定向状态目录(CI / 便携模式) |
LOCPILOT_HOME |
后端状态目录(历史、设置、runtime.json) |
python3 -m locpilot engines --probe # 引擎可用性与设备列表
python3 -m locpilot devices # 已连接设备
python3 -m locpilot set 31.2304 121.4737 # 单点传送
python3 -m locpilot clear # 恢复真实定位
python3 -m locpilot route --point 31.2304,121.4737 --point 31.2454,121.4987 --speed 6.9 --loop pingpong
python3 -m locpilot route --gpx track.gpx --speed 3 # GPX 回放
python3 -m locpilot export-gpx --point 31.23,121.47 --point 31.24,121.48 --out route.gpx
python3 -m locpilot search 上海外滩 # 地址搜索
python3 -m locpilot doctor # 环境自检(JSON)
python3 -m locpilot serve --port 8799 # 只跑后端(App 会自动拉起它)常用参数:--engine {auto,pymobiledevice3,go-ios,libimobiledevice,mock}、--udid、--json、--offline。
| 引擎 | 适用 | 隧道 | 许可 | 说明 |
|---|---|---|---|---|
| pymobiledevice3(默认) | iOS ≤16 与 17+ | iOS 17+ 需要(默认自动建立,免 sudo) | GPL-3.0 | 常驻 worker 会话,支持高频更新;CLI 兜底 |
| libimobiledevice | 仅 iOS ≤16 | 不需要 | LGPL-2.1 | 走 com.apple.dt.simulatelocation;iOS 17 起该服务不可用,引擎会明确拒绝 |
| go-ios | iOS ≤16 与 17+ | ios tunnel start --userspace |
MIT | 备选;实测结论:暂缓替换,需要闭源分发时再切 |
| mock | 任意 | — | 本项目 | 无设备演示与自动化验证 |
前置条件(真机):USB 连接并在手机上「信任此电脑」;iOS 16+ 需开启开发者模式
(idevicedevmodectl enable 或 pymobiledevice3 amfi enable-developer-mode,需重启并输入锁屏密码);首次使用建议 python3 -m locpilot doctor --probe 确认。
iOS 17+ 若自动隧道失败(例如 iOS 17.0–17.3),手动开一个共享隧道后重试:
sudo .venv/bin/pymobiledevice3 remote tunneld # 仅共享/持久隧道才需要 rootmacos/ 原生 App(SwiftPM 工程,命令行可构建,不需要 Xcode)
Package.swift LocPilotKit / LocPilotApp 两个 target
Sources/LocPilotKit/
BackendController.swift 后端守护:解释器探测、端口挑选、健康检查、日志转发、退出回收
EngineClient.swift REST + SSE 客户端(status / connect / disconnect / teleport / clear / events)
Sources/LocPilotApp/
LocPilotApp.swift App 入口、菜单、启动画面、--selftest 入口
AppState.swift 唯一状态源(连接状态 / 位置 / 相机),@Published 驱动界面
MapScreen.swift MapKit 地图 + 点击传送 + 坐标读数
ControlsCluster.swift 右上玻璃控件簇(系统 .glassEffect,旧系统回落材质)
WindowConfigurator.swift 全面屏窗口(推迟到下一 runloop 改窗口,避免布局期崩溃)
locpilot/ Python 后端(App 通过 HTTP 驱动,也可独立使用)
cli.py / server.py / api.py / config.py
core/ geo · route · playback · gpx · places · store · session
engine/ base · pmd3(含常驻 worker)· legacy · goios · mock
macos/build.sh 开发构建(产出 LocPilot.app)
macos/dist.sh 分发打包(清洗 + 重签名 + arm64 校验 + DMG + 校验和)
docs/images/ README 用的界面截图
关键设计取舍:
- 界面与引擎分离:原生 UI 只依赖
EngineClient的 HTTP 契约,引擎换代不影响界面。 - 常驻 worker 而非每次 spawn CLI:pymobiledevice3 的
simulate-location set会阻塞在 SIGINT,每次改坐标都重启进程会反复建立隧道;worker 只建一次会话,之后一行 JSON 一次坐标。 - 事件流驱动界面:
/api/events是 SSE。注意 Foundation 的bytes.lines不产出空行,SSE 分帧必须自己按字节切,否则事件流会静默失效(界面看着正常,实际全是死的)。 - 不在布局期改窗口:
WindowConfigurator把窗口配置推迟到下一个 runloop,并且禁用一切 KVC 私有键 —— 两者都曾导致启动即闪退(SIGTRAP)。 - 回放里程以几何为准:OSRM 返回的道路里程只作参考,否则会出现「进度 100% 人还没到」。
# 原生层(零依赖测试运行器:Command Line Tools 没有 XCTest)
swift run --package-path macos LocPilotTests
# 构建 + 打包结构自检 + 启动冒烟 + 崩溃守卫(新增崩溃报告即失败)
bash macos/build.sh --smoke
# 无界面自检(JSON,CI 用)
bash macos/build.sh --selftest
# 出分发包:移除本机路径 + ad-hoc 重签名 + arm64 校验 + DMG + SHA-256
bash macos/dist.sh产物在 macos/build/dist/:LocPilot-<版本>-arm64.zip + .sha256 + 安装说明.txt(优先出 DMG,环境不允许创建磁盘镜像时自动回落 ZIP)。
打包脚本会强制校验架构为 arm64、包内不含本机绝对路径,改过 Info.plist 后重新 ad-hoc 签名,最后解压到独立目录复核签名与 --selftest。
本机若只装了 Command Line Tools(无 Xcode):
swift test不可用(没有 XCTest),也不能用@State等 SwiftUI 宏; SwiftPM 需加--disable-sandbox并把模块缓存指到工程内。
- 系统级生效:改的是设备整体位置,不能只对单个 App 生效。
- IP 不改变:依赖 IP/Wi-Fi 定位的服务仍能看到真实地区。
- 可被检测:CoreLocation 暴露
isSimulatedBySoftware,游戏与风控可能识别模拟定位;请勿用于破坏服务条款或作弊场景。 - iOS 17+ 的定位随连接存活:DVT 连接断开即恢复真实定位,所以必须保持 App / 服务运行。
- iOS ≤16 的定位是设备侧状态:进程退出后仍保持,需
clear(或重启)才恢复。 - 需要开发者模式与 Developer Disk Image;锁屏 / 未信任设备无法工作。
- 原生版地图由 MapKit 提供,需要联网(Apple 地图服务)。中国区数据源即高德,对外坐标仍是 WGS-84,不需要自行做 GCJ-02 纠偏。
| 现象 | 处理 |
|---|---|
| 未发现设备 | 换数据线 / USB 口;手机点「信任」;python3 -m locpilot doctor --probe |
| iOS 17+ 报隧道错误 | 运行 sudo .venv/bin/pymobiledevice3 remote tunneld,或 --rsd HOST PORT |
not supported on iOS 17+ |
用的是 libimobiledevice 引擎,切回 --engine pymobiledevice3 |
| 启动即闪退 | 看 ~/Library/Logs/DiagnosticReports/LocPilot*;两类历史原因:KVC 私有键、布局期改窗口 —— 都已修并有冒烟守卫 |
| 界面显示已连接但状态不刷新 | 事件流问题:确认 EngineClient.events() 按字节分帧(bytes.lines 会吞掉 SSE 空行) |
| 坐标下发失败后回放暂停 | 查后端日志与 engine.error;重连设备后用 CLI / API 继续 |
PermissionError: …/.pymobiledevice3 |
家目录不可写(沙箱 / CI / 只读 HOME)。引擎会自动退到 <状态目录>/pmd3-home,也可显式指定 LOCPILOT_PMD3_HOME=/可写路径 |
默认只监听 127.0.0.1;/api 可加 --token 校验;静态资源做了目录穿越防护。
本工具会在本机执行设备控制命令,请勿把端口暴露到公网。
- 状态目录:
~/Library/Application Support/LocPilot(runtime.json记录 pid / 端口 / 解释器) - 后端日志:App 会转发后端 stdout/stderr;独立运行时在终端直接可见
- 菜单「引擎 → 打开状态目录」可直接在 Finder 打开
LocPilot 以 GPL-3.0 发布:默认引擎 pymobiledevice3 为 GPL-3.0,本项目在其之上构建并导入其 Python API。 若改用 go-ios(MIT)引擎并移除 pymobiledevice3 适配层,可自行改为宽松许可。 第三方归属见 NOTICE.md。
每个版本修了什么、加了什么,见 CHANGELOG.md;安装包与 SHA-256 见 Releases。
最近一版 v1.0.1 修掉了:窗口顶部悬停判定错位、红绿灯不显示 × − + 符号、首屏状态接口卡十几秒、无定位时左下角多出的横杠,并把系统控件外观切到新系统样式。
问题 / Bug / 建议:请提 Issue,这样别人也能搜到答案。
