ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

开源Skill让AI编程助手精通iPhone双机协同开发

开源Skill让AI编程助手精通iPhone双机协同开发 最近在折腾 iPhone 双机协同开发的时候我发现 AI 编程助手一个很典型的毛病你让它处理普通单机 App它头头是道可一旦涉及两台设备互相发现、组网、传数据它就变得非常外行一会儿记错权限配置一会儿把 MultipeerConnectivity 的 API 说得云里雾里。说白了通用模型很强但面对“iPhone Duo 开发”这种偏门又偏实践的领域它缺的是一套稳定的上下文。所以我花了两天时间把手头踩过的双 iPhone 联调经验整理成了一个开源 Skill直接喂给 AI 助手。装上之后效果立竿见影——它终于知道要先查 Info.plist知道两台设备要用同一个 serviceType也知道真机调试还得看证书和 UDID。这篇文章就把这个 Skill 从设计思路、目录结构到完整接入过程讲一遍iOS 开发者和日常重度使用 AI 编程工具的朋友都能直接照着抄。1. 这个 Skill 到底是什么一个“上下文注入包”1.1 iPhone Duo 开发指的是什么场景先说清楚一个概念。“iPhone Duo”并不是苹果官方的术语我在这个项目里把它定义为“两台 iPhone 协同工作相关的开发场景”。最典型的有三类双机联调也就是开发端和客户端各跑一台设备用来验证网络通信和数据同步跨设备互动 App比如双人游戏、共享白板、遥控器类应用还有就是混搭调试环境一台真机跑主逻辑另一台模拟器跑辅助模块。这类开发和普通单机 App 开发最大的差异在于代码逻辑只是其中一块更麻烦的是设备发现、网络权限、证书配置、后台保活、同步时序这些工程化问题。任何一个环节没配好两台设备就是互相“看不见”。而通用 AI 助手在训练语料里见过很多 API 名称但一到具体项目环境里它很难意识到你的 Info.plist 还缺一个 NSLocalNetworkUsageDescription也不知道你用的是免费开发者账号证书七天就会失效。这些恰好是人脑容易记住但 AI 容易忽略的“项目隐性知识”。如果每次都把这一大段背景塞进对话里又累又容易漏。做成 Skill 之后AI 每次进入相关任务之前就会被注入这套领域规则相当于给它装了一个“双机协同开发专用大脑”。1.2 为什么不直接复制 Prompt偏要做成 Skill有人可能会说我把这些规则写成一段长 Prompt 不就行了我最初也是这么干的但实际用了几天就放弃了。Prompt 是一次性的你不复制它就没了而且跟 AI 聊到后面上下文窗口被冲淡它越来越容易“忘记”你开头说的约束。Skill 则是持久化、结构化、可复用的能力包它不只是几行文字它还可以带脚本、带工具白名单、带示例代码。我用一个表格来说明它和普通方案的差别对比项长 Prompt插件Skill持久性需每次粘贴上下文易冲淡系统级能力较重项目级或用户级常驻按需触发结构纯文本逻辑靠人脑维护代码级集成需写插件 APIMarkdown 规则 可选脚本结构清晰动态执行无法主动调用命令可以但开发成本高可通过 scripts 目录运行 Shell 脚本适用人群想快速试一下的人有插件开发能力的开发者普通使用者到团队维护者都能用现在主流的 AI 编程助手其实都支持类似的机制。Claude Code 用的是.claude/skills/skill-name/SKILL.mdCodex 支持项目级的AGENTS.mdCline 这类工具也有自己的规则文件。本质上都是同一件事在 AI 开始干活之前先让它读入一套和当前任务强相关的领域规则。我这个开源 Skill 就是基于这套通用思路做的你放到哪个工具里只要路径对就能生效。2. 设计这个 Skill 时我先拆了四个核心问题2.1 让 AI “秒懂”双机协同的术语和框架AI 对“iPhone Duo 开发”犯迷糊一半原因是术语和框架知识太散。所以我做的第一件事就是在 Skill 文档里内置了一份术语表和框架速查。凡是我在双机协同开发里高频用到的框架都写了用途、关键类和典型坑MultipeerConnectivity最常用的近场点对点通信方案负责设备发现、会话建立、数据传输的整套流程。CoreBluetooth低功耗蓝牙方案适合数据量小、对耗电敏感的场景但需要处理外设与中心的配对关系。Network.framework基于 TCP/UDP 的自定义协议适合局域网内大量数据传输但要自己处理设备发现。NearbyInteraction利用 U1 芯片做空间感知适合做相对位置判断不过目前设备支持有限。除了框架名称我还会在里面明确写出权限配置。因为这是 AI 最容易编错的地方。比如 MultipeerConnectivity 在 iOS 14 以后必须要在 Info.plist 里声明NSLocalNetworkUsageDescription如果走 Bonjour 发现服务还得加上NSBonjourServices。没有这些字段设备协商阶段会直接失败控制台里出现的报错又不是很直观。我把这些内容写成一个“参考块”明确要求 AI 在输出代码或检查配置前先对照这个清单。这样做的好处是AI 不再从自己的记忆里“猜”权限配置而是先读文档再干活准确性提高了一大截。2.2 把联调流程固化成 AI 的行动规则第二个问题是流程意识。通用 AI 写单机代码可以“随手就来”但双机联调这种事情步骤错一步后面就全乱。比如它可能会直接让你去写会话数据发送却忘了你已经连着两台真机但证书早过期了或者两个 target 连接的是同一个模拟器实例设备 ID 都对不上。所以我在 Skill 里用编号规则定义了一套联调检查流程先检查 Xcode 工程配置确认当前 target 和 bundle identifier。再检查 Info.plist 里有没有本地网络权限描述和必需的 Bonjour 服务声明。然后检查签名与设备确认目标设备 UDID 已注册证书是否在有效期内。编译跑通后再进入设备发现和连接验证。最后才能开始写数据传输和业务逻辑。这套规则我会用“必须按顺序执行不得跳步”这种强约束写在文档里。实测下来AI 在大部分情况下会乖乖照做即使它觉得某个步骤多余也会先向我确认而不是自作主张跳过。2.3 给 AI 补上“手”脚本化设备信息采集文档和规则让 AI “懂行”但有时候它还缺“手”。比如它想检查当前连接的设备说得再头头是道都不如让它真的执行一条命令拿到准确结果。所以这个 Skill 里我放了一个scripts/目录里面是几个极简的 Shell 脚本。其中一个脚本用来列出当前可用的模拟器和真机核心就一条命令xcrun xctrace list devices如果只关心模拟器可以用xcrun simctl list devices还有一个脚本负责读取某个模拟器的系统日志方便在联调失败时直接抓取 MultipeerConnectivity 的底层报错xcrun simctl spawn booted log stream --predicate subsystem com.apple.multipeer真机上抓日志则走log stream命令配合设备 ID 过滤。这些脚本本身都不复杂但对 AI 来说意义很大它可以从“凭空猜测”变成“先采集信息再判断”。我还在 Skill 的 frontmatter 里用allowed-tools限制了命令范围避免它顺手执行一些有副作用的重置操作。2.4 明确边界AI 不能碰什么技术能力补上之后还要给它划红线。这也是我从几次“翻车”经历里总结出来的。AI 有时候非常主动看到签名报错第一反应是自己去帮你改Signing Capabilities里的配置或者往 Info.plist 里塞一个看起来很合理的字段。这种“越权”在双联调场景里特别危险因为你根本不知道它悄悄改了什么。所以我在 Skill 里写了一条硬性规则签名、证书、描述文件相关配置只能检查、不能修改必须由开发者手工处理App Transport Security 的改动必须经过确认任何“清空设备数据”“删除 DerivedData”之类的破坏性操作一律先说明风险再执行。设置边界不是限制 AI 的作用反而能让它在安全范围内放开手脚你敢让它跑的东西它才能替你干。3. 实操把 Skill 装进 AI 助手并跑起来3.1 前置准备设备和环境在装 Skill 之前先把联调环境准备好。最省事的组合是一台真机加一台模拟器但如果你要验证真实的蓝牙或近场体验最好准备两台真机。个人免费 Apple ID 也能跑真机调试但会有签名七天过期的限制这个我后面在排查部分会单独讲。你需要确认几件事Mac 上装好了 Xcode并且已经用你的 Apple ID 登录目标真机已经连接电脑并信任了这台 Mac如果你想用局域网通信两台设备要连同一个 Wi-Fi如果走 MultipeerConnectivity还要把蓝牙打开。最后在终端里跑一下xcrun xctrace list devices确认能看到你真机的 UDID这一步通过环境就算没问题了。3.2 目录结构长这样这个 Skill 的目录结构参考了 Claude Code Agent Skills 的规范同时也兼顾了其他工具的兼容性。整个项目就是这样一个树形结构iphone-duo-dev-skill/ ├── README.md ├── SKILL.md └── scripts/ ├── list_ios_devices.sh └── stream_device_log.shSKILL.md核心文件所有给 AI 的领域知识、规则、流程和示例都写在这里。README.md给人类看的安装说明也可以放一些常见问题的解决办法。scripts/存放 AI 在任务中可调用的辅助脚本。如果你用的是支持 Agent Skills 的工具直接把整个目录放到项目下的.claude/skills/或用户级目录里就能识别。如果你的工具走的是AGENTS.md之类的单文件规则那说明文件里也可以引用这个目录下的脚本只需要把路径写清楚。3.3 用 SKILL.md 把领域规则写给 AISKILL.md是这个项目的灵魂。它的头部是 YAML frontmatter写上技能名称、描述、允许使用的工具。description是 AI 判断“什么时候该调用这个 Skill”的关键所以要写得具体一点不能只写“帮助 iPhone Duo 开发”而要写出触发条件比如“当用户讨论两台 iOS 设备之间的发现、连接、数据同步或联调时”。结构大致是这样--- name: iphone-duo-dev description: Assist with iOS dual-device development, including device discovery, MultipeerConnectivity, local network permissions, signing and device deployment. allowed-tools: - bash - gh --- # iPhone Duo 开发助手 ## 1. 领域背景 iPhone Duo 开发指两台 iOS 设备协同工作的场景…… ## 2. 核心规则 - 先检查权限配置再写业务代码 - 所有 MultipeerConnectivity 的 serviceType 不得超过 15 字节…… - 不直接修改签名配置只提示开发者手动处理 ## 3. 设备与联调流程 按编号步骤执行…… ## 4. 常用框架速查 MultipeerConnectivity / CoreBluetooth / Network.framework…… ## 5. 示例交互 给出一个标准问答示例……正文里的措辞我用了很多祈使句比如“必须”“不要”“先”这类强约束词因为大模型对指令强度的感知比较敏感弱约束很容易被它忽略。同时我也放了一个“示例交互”小节让 AI 知道当用户提出需求时一个合格的回答应该是什么样子的这相当于“少样本提示”的作用比单纯讲规则更有效。3.4 如何验证 AI 真的加载了 Skill装好之后别急着开工先验证一下 AI 是否真的读到了这套规则。最简单的方法是直接在对话里问它“你当前加载了哪些可用技能iphone-duo-dev 的核心规则有哪些”如果它能准确说出 serviceType 长度限制和权限检查顺序说明加载成功了。如果它答不上来大概率是目录没放对。还有一种更隐蔽的情况项目和用户级同时存在多个同名 Skill工具会优先读某一个另外一份就被忽略了。为了避免这种情况我习惯在SKILL.md里放一句只有这个版本才有的“暗号”比如一个特定的规则编号或者提示词然后让 AI 复述出来这样能确认它读到的到底是不是我最新改的那份。4. 实战让 AI 助手完成一次双机联调4.1 一个典型的 Duo 功能需求光说不练假把式。我用自己的测试工程跑了一遍完整流程这个工程已经建好了两个 target分别对应两台设备上的主端和从端但完全没有联调代码。我让 AI 实现一个最简单的功能两台 iPhone 通过 MultipeerConnectivity 自动发现并互相发送一句话。这个场景虽然简单但里面藏了很多容易出错的点本地网络权限、服务类型、设备发现回调、会话状态变化、数据收发线程。任何一个细节错了整个流程都跑不通非常适合用来验证 Skill 的实际效果。4.2 AI 拿到工程后做了什么加载 Skill 后AI 没有一上来就疯狂生成代码。它先主动读了一遍我的工程目录然后列出了它要执行的计划先检查 target 配置然后检查 Info.plist再检查当前连接的设备列表最后才会把 MultipeerConnectivity 的核心代码写出来。它给出的接入方案有几处让我印象很深。它特别提醒我主端和从端的 serviceType 必须完全一致并且要符合苹果的命名规范两台设备需要同时开启本地网络权限否则广告和浏览都会失败在 iOS 14 及以上系统第一次触发时系统会弹权限框用户没有允许之前不会进行任何发现动作。这些细节虽然我在 Skill 里写了但 AI 能把它们变成一套有逻辑的步骤而不是零散地堆给我说明规则确实起了作用。4.3 落代码后必须人工核对的三件事即使 AI 表现好我也不建议让它完全甩手。每次它生成联调代码之后我都会花三分钟人工核对三个关键点第一MultipeerConnectivity 的回调方法是否在正确的线程处理。session(_:didReceive:fromPeer:)默认不在主线程如果有 UI 更新必须手动派发回主队列。第二Info.plist 里的NSLocalNetworkUsageDescription是否真的存在而不是 AI 只在代码注释里提了一句。第三会话生命周期有没有正确处理尤其是设备断开之后重新连接的逻辑这是一个非常容易漏掉的状态转换。我这次拿到的代码里前两个点都通过了但 AI 在设备断开重连时的状态处理写得比较草率。它只实现了didChange回调里打印状态没有补上重新邀请的逻辑。这个不算错误但距离“可上线”还有差距。我直接把这个问题反馈给它它很快就补出了重连方案。4.4 实测效果与调整经验从跑通整个流程的时间来看有 Skill 和没有 Skill 的区别非常明显。之前靠直接对话光是在权限配置上来回折腾就花了快一个小时这次从提出问题到两台设备互发消息成功大约只用了十五分钟其中大部分时间还是花在 Xcode 编译上。测完以后我又顺手调了一版 Skill 规则。因为我发现 AI 虽然记得 serviceType 有长度限制但还是会在示例代码里顺手写一个超过 15 个字符的服务名。后来我在“常用框架速查”里专门加了一行醒目提示并提供了一个合法示例app-p2p这个问题基本就消失了。这说明 Skill 是需要持续迭代的每踩一个坑就把它补进规则里。5. 常见问题与排查技巧5.1 AI 没有加载 Skill怎么办我在社区里见过不少朋友反馈说“按文档装了但没生效”。第一个要查的是路径不要放错地方。以 Claude Code 为例项目级路径是.claude/skills/iphone-duo-dev/SKILL.md用户级路径是~/.claude/skills/iphone-duo-dev/SKILL.md。你放在两个地方都行但同名 Skill 会导致工具不知道读哪个建议只留一处。第二个要查的是 frontmatter。name字段里的字母和数字有严格限制不能有空格或特殊符号如果格式解析失败整个 Skill 不会被加载。遇到这种情况最简单的验证方法是把文件内容减少到只剩一个极简规则看工具能不能识别排除掉大段内容里的格式问题。5.2 两台设备互相发现不了这个问题的原因排列组合太多了。按照我从 Skill 的规则里总结的经验排查顺序应该是先看两台设备在不在同一个 Wi-Fi 下再看蓝牙是不是都开着然后检查系统权限弹窗有没有被用户拒绝最后用日志确认广告和浏览是不是同一 serviceType。最常见的坑就是本地网络权限没开启系统可能会静默遮断设备发现连报错都不太明显。我遇到过一次很奇怪的情况两台真机都能看到对方设备名但 session 一直连不上。最后查了半天发现是其中一台设备的系统年份设置不对导致 TLS 握手失败。这种问题如果不是看系统日志光靠脑子想很难定位所以我在 Skill 里特地加了一条规则联调失败时不要瞎猜先抓日志。5.3 AI 写出的 API 过时或不准确大模型的知识有截止日期API 也一直在变所以 AI 偶尔会写出一段“长得像对的”废弃接口。遇到这种情况我一般会直接让它先跑文档命令再回答。在命令行界面里可以引导它访问苹果官方文档页面。还有一种办法就是给 Skill 增加一个“参考文档列表”小节把当前项目依赖的 iOS 版本对应的文档地址放进去AI 在拿不准时会优先查看这些链接。另外把项目里的真实报错信息直接贴回对话也很重要。你让 AI 按报错关键词重新推理比让它凭空重写代码有效得多。这是我用 AI 写 iOS 代码半年来的一个核心心得报错信息就是最好的提示词。5.4 问题速查表现象可能原因处理方式Skill 未生效路径不对或 frontmatter 解析失败检查目录和 name 字段只保留一份同名 Skill设备互相看不到本地网络权限未开启检查 Info.plist 和系统弹窗授权状态能发现但连接失败serviceType 不一致或系统时间异常统一 serviceType核对设备系统时间偶尔能连上、偶尔不行蓝牙或 Wi-Fi 不稳定换一个干扰少的频段关闭设备省电模式真机安装后很快失效免费证书七天过期重新登录 Apple ID 或使用付费开发者账号5.5 几个容易踩的隐藏坑最后分享几个很隐蔽的坑。第一个是 MultipeerConnectivity 的 serviceType 命名苹果要求只能包含小写 ASCII 字母、数字和连字符长度不能超过 15 个字节。很多人用驼峰命名或者带下划线结果设备发现时表现得很不稳定。第二个是在模拟器上测试时模拟器共享 Mac 的网络权限有时候真机能发现模拟器但模拟器发现不了真机这种不对称情况会让人误以为代码写错了。第三个是真机调试时的证书周期问题。用免费 Apple ID 签名的 App 七天就会失效如果联调到一半突然装不上先查一下证书是不是过期了别急着去改代码。我在 Skill 的“常见陷阱”部分写了一个小技巧真机联调前先给设备设一个日历提醒每六天提醒重新签名一次可以省掉不少临场排查的时间。6. 后续还能怎么扩展6.1 从“辅助联调”进化到“代码评审和测试生成”这个 Skill 目前主要解决联调场景但我已经在计划下一版的方向。一个是把它扩展成代码评审规则集让 AI 在检查 Pull Request 时主动核对 MultipeerConnectivity 相关的边界条件和权限隐患。另一个是让它根据联调场景生成基础测试用例比如会话断开重连、弱网环境、权限拒绝之后的行为这些手工写起来费时费力的场景很适合交给 AI 打底稿。6.2 把 Skill 做成团队共享的知识库如果团队里有多个人都在做双机协同开发Skill 完全可以变成团队基础设施的一部分。把这份文件放进 Git 仓库里统一管理每次有人踩了新坑就补一条规则提交之后大家都能用到。因为它是开源项目社区里的反馈和 PR 也能帮助完善内容让这套知识越来越厚。我实际用了几天之后最大的感受是Skill 本质上是把你踩过的坑固化成 AI 的行为约束。它不是万能灵药有时候还是需要你人工判断和现场排查但至少 AI 不会再对着 MultipeerConnectivity 瞎编权限配置也不会把两台设备的证书问题归因到一模一样的代码上。每次联调踩到新坑我都会顺手把它补进 Skill 的规则里几天下来这份文件就像长了记性一样越来越懂这个项目。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进