Windows 怎么做 iOS UI 自动化?WebDriverAgent 操作 iPhone
一条命令把 WebDriverAgent 签名装到 iPhone 上并启动,用脚本、测试框架或 AI 代理点击、滑动、输入、按文字找控件和截图。
最后更新
在 Windows 做 iOS UI 自动化,用 kxdevice test runwda 一条命令把 WebDriverAgent(WDA,Appium 在 iPhone 上使用的 UI 自动化服务)签名、装到手机并启动,之后脚本、测试框架和 AI 代理通过本机 8100 端口点击、滑动、输入文字、按文字查找控件、读取界面层级和截图。Linux、macOS 上用法相同,手机需要 iOS 17 及以上。
Windows 做 iOS UI 自动化要准备什么?
连接手机
手机已信任这台电脑并打开开发者模式,步骤见设备准备。多台手机时,加 --udid 指定用哪一台。
在共用证书目录放好开发证书
WDA 用 KXBUILD_HOME/keychain/ 里的证书签名,工程目录下的 keychain 不参与。放一张 Apple Development 证书和一个包含这台手机的开发描述文件。
App ID 为 * 的通配描述文件最省事;只有 com.yourcompany.* 这类通配描述文件也可以,WDA 会自动改用 com.yourcompany.WebDriverAgentRunner.xctrunner 这个 bundle ID。只有某个 App 的描述文件时,见这里。放法见 Windows 给 iOS App 签名。
怎么在 iPhone 上启动 WebDriverAgent?
第一次运行时会自动签名、安装再启动,以后直接启动。WDA 就绪后命令会打印 WebDriverAgent is ready at http://127.0.0.1:8100,之后脚本就可以访问这个地址。命令会一直运行,用完按 Ctrl-C 停止。
> kxdevice test runwda也可以用浏览器打开 http://127.0.0.1:8100/status,返回内容里有 "ready" : true 就是可用的。
没有通配描述文件,怎么修改 WDA 的 bundle ID?
如果你没有带通配符的描述文件,但有其他 bundle ID 的开发描述文件可以用来给 WDA 签名,可以用 --bundle-id 把 WDA 的 bundle ID 改成那个描述文件的 bundle ID。
> kxdevice test runwda --bundle-id com.example.myapprunwda 有哪些参数?
| 参数 | 什么时候用 |
|---|---|
| --reinstall | 升级 KXBuild 之后,或换了证书、描述文件之后,重新签名安装 |
| --no-install | 手机上已经装好 WDA,只启动不检查 |
| --ipa <文件> | 用你自己编译的 WDA runner 代替内置的那份 |
| --bundle-id <ID> | 把 WDA 的 bundle ID 改成指定值,签名后安装到手机,见上文 |
| --port <端口> | 本机 8100 端口被占用时换一个,例如 --port 8101,脚本就访问 8101 |
| --no-forward | 不占用本机端口,自己用 kxdevice forward 转发 |
| --udid <UDID> | 接着多台手机时指定一台。同时驱动几台时,每台用不同的 --port |
| -v | 显示 WDA 自己的输出,排查启动问题时用 |
怎么用 Python 脚本驱动 WDA 做 UI 自动化?
WDA 使用 WebDriver 协议,任何语言发 HTTP 请求都能驱动。下面的 Python 例子打开「设置」,按文字找到「通用」并点击,再截一张图。查找控件用的是界面上显示的文字或无障碍标签,App 是中文界面时就写中文。
> pip install requestsimport base64, requests
WDA = "http://127.0.0.1:8100"
# 打开 App,得到会话
r = requests.post(f"{WDA}/session", json={
"capabilities": {"alwaysMatch": {"bundleId": "com.apple.Preferences"}}})
sid = r.json()["sessionId"]
# 按文字查找控件并点击
r = requests.post(f"{WDA}/session/{sid}/element",
json={"using": "accessibility id", "value": "通用"})
el = r.json()["value"]["ELEMENT"]
requests.post(f"{WDA}/session/{sid}/element/{el}/click")
# 截图
png = requests.get(f"{WDA}/screenshot").json()["value"]
open("screen.png", "wb").write(base64.b64decode(png))
requests.delete(f"{WDA}/session/{sid}")把 bundleId 换成你自己 App 的。常用接口如下,路径前都加 http://127.0.0.1:8100。
| 要做的事 | 请求 |
|---|---|
| 检查是否就绪 | GET /status |
| 打开 App 并创建会话 | POST /session,capabilities 里写 bundleId |
| 按文字或标签找控件 | POST /session/<会话>/element,using 为 accessibility id |
| 点击控件 | POST /session/<会话>/element/<控件>/click |
| 屏幕尺寸(单位是点) | GET /session/<会话>/window/size |
| 界面层级,查控件的名字和位置 | GET /source |
| 截图,返回 base64 编码的 PNG | GET /screenshot |
| 回到主屏幕 | POST /wda/homescreen |
| 结束会话 | DELETE /session/<会话> |
不知道控件叫什么时,先请求 /source,在返回的 XML 里找 name 或 label 属性。滑动、长按、输入文字等其他接口与 Appium 的 WebDriverAgent 相同,可以查 WebDriverAgent 项目的文档。
怎么让 AI 代理操作 iPhone?
把 kxdevice 添加为 MCP 服务器后,Claude Code、Cursor 等 AI 代理可以点击、滑动、输入文字、按文字查找控件、读取界面层级,用来自己验证改动后的界面。代理第一次调用这类工具时,kxdevice 会自动启动 WDA,不用手动运行 runwda。以 Claude Code 为例
> claude mcp add kxdevice -- kxdevice mcpWDA 常见报错怎么处理?
| 现象 | 处理 |
|---|---|
| 签名或安装失败 | 检查 KXBUILD_HOME/keychain/ 里有没有开发证书和包含这台手机的开发描述文件,补好后加 --reinstall 重新运行 |
| 提示 WebDriverAgent 组件不存在 | 运行 kxbuild doctor 装上缺少的组件 |
| 提示需要 iOS 17 | WDA 只支持 iOS 17 及以上,先升级手机 |
| 提示 8100 端口被占用 | 停掉之前还在运行的 runwda 或 kxdevice forward,或者加 --port 8101 换一个端口,脚本里的地址也改成 8101 |
| 一直没有打印 ready | 先解锁手机。还不行就按 Ctrl-C 停止,加 -v 重新运行,查看 WDA 的输出 |
| 按文字找不到控件 | 文字要和界面上显示的完全一致,包括语言。请求 /source 查看控件实际的 name 和 label;自己的 App 可以给控件设置 accessibilityIdentifier |
表里没有的启动问题,加 -v 重新运行 runwda,可以看到 WDA 自己的输出。环境排通之后,Windows 做 iOS UI 自动化的日常流程就是:运行 runwda、跑脚本、按 Ctrl-C 停止。需要同时真机调试时,见 VS Code 真机调试 iOS App。
常见问题
UI 自动化支持哪些 iOS 版本?
支持 iOS 17 及以上的 iPhone,更低版本需要先升级系统。手机还要信任这台电脑并打开开发者模式。
一定要用 Python 写脚本吗?
不用,WDA 使用 WebDriver 协议,任何能发 HTTP 请求的语言或测试框架都能驱动,Python 只是示例。
能同时控制几台 iPhone 吗?
能,每台手机各运行一个 runwda,用 --udid 指定手机,用 --port 分配不同端口,例如 8100 和 8101,脚本分别访问对应端口。
AI 代理用之前要先手动运行 runwda 吗?
不用,把 kxdevice 添加为 MCP 服务器后,代理第一次调用点击、滑动这类工具时 kxdevice 会自动启动 WDA。