开源Skill让AI助手真正掌握iPhone Duo多屏适配与UIWindowScene开发

发布时间:2026/9/23 2:49:40
开源Skill让AI助手真正掌握iPhone Duo多屏适配与UIWindowScene开发 如果你的 AI 助手也曾在“iPhone Duo 开发”这个话题上给你瞎编 API那你一定要看看这个开源 Skill。所谓 Duo 开发我指的是 iPhone/iPad 连接外接显示器、多窗口并行、以及折叠形态切换这类“一机多屏”的适配工作。过去半年我一直在带 AI 助理做 iOS 工程最头疼的就是这类问题它能把 UISplitViewController 讲得头头是道却不知道外接屏要单独挂一个 UIWindowScene它能给你列一堆 iPad 分屏指南却对 UIWindowSceneDelegate 的完整生命周期一知半解。后来我在 GitHub 上找到了这个开源 Skill装进 Claude Code 之后AI 的回答质量明显上了一个档次。这篇文章我会拆解它的设计思路也会把 iPhone Duo 开发里最容易踩的坑一并整理出来适合正在用 AI 写 iOS 代码、或者想自己做领域 Skill 的开发者。1. 这个开源 Skill 解决了 AI 编程助手的什么痛点1.1 先搞清楚iPhone Duo 开发到底在说什么很多朋友第一次看到 Duo 这个词会以为是什么新框架其实它更像一个“场景集合”。从 iOS 13 开始苹果把 App 的界面从“一个 App 一个 Window”改成了“一个 App 可以拥有多个 Scene”每个 Scene 独立管理自己的生命周期。Duo 开发就是围绕“多 Scene 多窗口 多形态屏幕”展开的适配工作典型场景包括iPad 通过随航或者有线连接外接显示器App 要在外屏上开第二个窗口iPhone 投屏到电视或外接屏后需要渲染不同内容未来折叠屏设备出现后同一界面要在展开和折叠两种形态下自动布局。这套东西在 Apple 的官方文档里分散在 UIScene、UIWindowScene、UIScreen 好几个章节里没有一个统一的“Duo 开发”入口。而 AI 助手的训练数据里这些内容占比又特别低所以一聊到具体实现AI 就很容易拿 iPad 分屏那套逻辑来糊弄你。1.2 AI 助手在外接屏问题上为什么总翻车我总结了几个典型的“翻车现场”你们可以拿自己的 AI 助手试试问“外接显示器上怎么创建窗口”AI 可能直接给你UIWindow(frame: UIScreen.main.bounds)这种老代码然后在 iOS 13 的工程里必炸问“外部屏断开后怎么清理资源”AI 大概率会教你在viewWillDisappear里做释放实际上正确姿势是监听UIScreen.didDisconnectNotification或处理 Scene 销毁回调问“折叠屏适配怎么做”AI 有时候会把 Android 的onConfigurationChanged概念硬搬到 iOS 上说出来全是槽点。说白了不是 AI 不聪明是这类知识在公开语料里太稀疏而且 API 迭代太快。传统做法是把几十页文档塞进系统提示词但效果很差一是上下文窗口有限塞不进去二是每次对话都加载一堆无关文本反而干扰 AI 判断。开源 Skill 的出现就是为了解决这个“领域知识按需加载”的问题。1.3 Skill 和普通提示词、Agent 到底有什么区别这块热度很高很多人问。直接给结论提示词是一次性输入的文本prompt 写完就固定了适合通用指令Skill 是一个包含知识文档、规则、脚本的目录AI 会在需要时主动读取而且能按任务动态选择读哪几个文件Agent 是能自主规划、调用工具、执行多步任务的“执行体”Skill 相当于它脑子里的“专业领域手册”。简单类比普通提示词是给 AI 贴一张便利贴Skill 是在它桌上放一本随时可以翻的工具书Agent 是那个自己会决定去翻哪本书、然后动手干活的人。所以这个开源项目的本质就是把你脑子里的 iPhone Duo 开发经验固化成一本书让 AI 照着翻。2. 拆解 Skill 的整体设计与知识组织方式2.1 一个标准的领域 Skill 目录结构长什么样这个开源项目最值得学习的是它的目录组织。克隆下来之后结构大概是这样的skills/ iphone-duo/ SKILL.md references/ 01-scene-lifecycle.md 02-external-display.md 03-multiwindow-management.md 04-adaptive-layout.md 05-faq-common-mistakes.md scripts/ check_deprecated_api.py examples/ ExternalWindowDemo/SKILL.md是入口文件负责告诉 AI“我是什么、什么时候该用我、核心规则是什么”。references目录放的是真正的中长篇幅知识文档AI 只有判断当前问题需要时才去读。scripts可以放一些校验脚本比如检查你生成的代码里有没有用到废弃 API。examples则放可直接运行的示例工程。这个设计思路非常聪明不是把所有资料都一股脑塞给 AI而是让 AI 先看目录按需翻页。和人查工具书是一个道理没人会把整本书背下来才动手干活。2.2 知识分层的三个层级概念、API、工程模板这个 Skill 里把知识库分成了三层我觉得这是它“秒懂”的关键。第一层是概念澄清。比如明确“外部屏有自己的 UIWindowScene而不是往主 window 上 addSubview”“多窗口不是多线程Scene 的生命周期由系统管理”。这些概念不清AI 写出来的代码一定歪。第二层是 API 速查。包括UISceneSession.Role.windowExternalDisplay、UIWindowSceneDelegate、UIScreen.didDisconnectNotification、traitCollection、sizeClasses这些核心 API 的用途、最低系统版本、注意点。AI 有了这份速查表就不会再编造 API。第三层是工程模板。比如一个最小的外部窗口示例工程、一个自适应布局的 SwiftUI 视图、一个管理内外屏状态共享的 ViewModel 示例。AI 在回答“帮我写一个外接屏播放器”之类的问题时可以直接参考模板改而不是从零开始编。三层结构的好处是AI 先通过 SKILL.md 判断问题类别再决定读取哪一层的哪个文件避免一次加载过多无关内容。2.3 为什么知识要写成“约束”而不是“自由文档”这一点是这个开源项目和我之前自己写 prompt 最大的区别。普通资料文档是陈述性的比如“UIWindowScene 是用来管理窗口场景的”AI 读了顶多算“知道”但生成代码时该犯的错还是会犯。这个 Skill 里的规则全是命令式的硬约束比如“禁止在 iOS 13 使用手动创建 UIWindow 的方式连接外部屏幕必须通过 UIScene 体系管理”“所有 API 建议必须标注最低系统版本遇到 deprecated API 要提示替代方案”“涉及多窗口共享数据时必须使用单一数据源禁止在多个 ViewController 里各存一份状态”。约束写得越具体AI 的“自由发挥空间”就越小生成结果就越稳定。这就像面试的时候给候选人划了考试范围他至少不会把答案写到隔壁科目去。3. 核心知识点实操真正把 iPhone 多屏开发写对3.1 外接显示器的正确接入姿势别再手动 new UIWindow 了我发现很多开发者对外接屏的第一反应是“手动创建 UIWindow 然后 addSubview”这是 iOS 13 之前的老思路现在这么写大概率会遇到黑屏或者布局错乱。正确姿势是走 Scene 体系。首先在 Info.plist 里声明外部屏 Scene 配置。你需要在UIApplicationSceneManifest下的UISceneConfigurations中加入UIWindowSceneSessionRoleExternalDisplay这一项指定对应的UISceneDelegateClassName。然后在场景代理里处理连接func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene scene as? UIWindowScene else { return } if session.role .windowExternalDisplay { externalWindow UIWindow(windowScene: windowScene) externalWindow?.rootViewController ExternalDisplayViewController() externalWindow?.makeKeyAndVisible() } }这段代码的核心在于判断session.role只有.windowExternalDisplay才走外部屏分支。别小看这个判断不判断的话内屏和外屏的初始化逻辑混在一起后面想拆都拆不开。3.2 内屏与外屏的生命周期管理比想象中麻烦外接屏最大的坑是“不确定”。用户随时可能拔掉线缆屏幕随时可能断连如果不在断连时清理窗口就会留下野指针、内存泄漏甚至崩溃。断连监听可以这样加NotificationCenter.default.addObserver( forName: UIScreen.didDisconnectNotification, object: nil, queue: .main ) { [weak self] _ in self?.externalWindow nil self?.externalRootViewController nil }这里有个细节externalWindow要写成强引用属性否则 ARC 会在窗口不可见时把它释放掉而断开时又要主动置 nil防止窗口持有过期的视图控制器。很多 AI 生成的代码只会教你创建不会教你销毁这恰恰是多屏开发的命门。另外在多窗口场景下SafeArea 的处理也很容易翻车。外接屏的 SafeArea 跟主屏完全不是一个概念刘海屏的 safeAreaInsets 到了外接屏上可能全是 0也可能因为分辨率不同出现上下黑边。正确做法是不要硬编码任何边距全部基于view.safeAreaLayoutGuide和windowScene.screen的实际尺寸动态计算。3.3 自适应布局与未来折叠屏的思路很多问 Duo 开发的人其实真正关心的是折叠屏。虽然苹果还没出折叠设备但苹果早就通过 Size Classes、traitCollection 这套机制帮开发者铺好了路。核心逻辑就一句话界面必须响应 trait 变化而不是响应设备名称。你可以监听traitCollectionDidChangeoverride func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) if traitCollection.horizontalSizeClass ! previousTraitCollection?.horizontalSizeClass { updateLayout(for: traitCollection.horizontalSizeClass) } }至于内外屏的内容同步我的建议是建立共享的ObservableObject或StateStore让内屏和外屏的 ViewController 都订阅同一份数据源。这样哪怕外屏断连重连数据也不会丢。这跟 SwiftUI 里的StateObject共享思路一致本质上是“把状态和视图解耦”。4. 怎么把这个开源 Skill 装进你的 AI 助手并验证效果4.1 安装步骤与路径选择这个 Skill 的安装并不复杂核心是把它放到 AI 助手能识别到的 Skills 目录。不同工具的默认路径略有差异以我实际用过的为例Claude Code项目级目录.claude/skills/iphone-duo/或者用户级目录~/.claude/skills/iphone-duo/Cursor项目级目录.cursor/skills/iphone-duo/Codex用户级目录~/.codex/skills/iphone-duo/。实操命令大概是git clone https://github.com/your-fork/iphone-duo-skill.git mkdir -p ~/.claude/skills cp -r iphone-duo-skill/skills/iphone-duo ~/.claude/skills/放在项目级目录的好处是跟着仓库走团队所有人都能共享放在用户级目录的好处是全局生效任何项目都能用。我个人的习惯是普通项目放用户级专门做多屏适配的项目放项目级。4.2 怎么验证 Skill 是否真的生效装完别急着写代码先做一轮“冒烟测试”。我的测试方法是问三个标准问题“iPad 连接外接显示器后怎么在一个新的 UIWindowScene 里展示内容”“外部屏断开时我应该在哪里清理资源”“写一个自适应折叠屏布局的 SwiftUI 示例。”如果 AI 的回答里出现了UIWindowScene、.windowExternalDisplay、UIScreen.didDisconnectNotification这些关键词说明 Skill 已经被正确加载。如果它还在跟你扯UIScreen.main.bounds大概率是 Skill 没被识别到或者 description 写得太模糊AI 没判断出来该用它。还有一种更直接的验证方式在提问时明确说“请参考 iphone-duo skill”。正常的 Skill 实现会把这个词作为触发信号强制加载相关文档。当然最好还是靠 description 自然触发因为你不可能每次对话都手动提醒它。5. 从零写一个领域 Skill 的实操方法论5.1 让 Skill 精准触发description 才是灵魂如果你也想给自己熟悉的领域做一个 Skill最重要的不是堆多少知识文档而是把 description 写好。AI 判断“要不要用这个 Skill”就靠它写得太窄该触发时不触发写得太宽什么题都往里塞容易干扰主线任务。一个合格 description 的写法是“场景 关键词 边界”。举个例子description: 当用户询问 iPhone/iPad 外接显示器、多窗口、多屏适配、外部 UIWindowScene、随航、扩展显示器、折叠屏/可变形态布局、UIWindowSceneDelegate 生命周期等问题时使用。不处理普通单屏 UI 布局问题。这段描述里的“不处理”三个字特别重要它帮助 AI 排除了模糊问题。少了边界说明AI 可能连“怎么给 UITableView 写代理”这种问题都来翻这个 Skill纯粹浪费上下文。5.2 SKILL.md 黄金模板直接抄作业这个开源 Skill 的SKILL.md写得非常规整我提炼了一个通用模板你们做自己的 Skill 可以直接套--- name: your-skill-name description: 当用户询问...时使用不处理...问题 --- # 知识领域名称 ## 核心规则 1. 必须基于 xxx 体系禁止使用 xxx 旧方案 2. 涉及 API 时必须标注最低系统版本和废弃状态 3. 给出代码示例时必须包含错误处理逻辑 ## 知识索引 - 概念澄清references/01-concept.md - API 速查references/02-api.md - 工程模板references/03-template.md ## 验证清单 在给出最终答案前检查 - [ ] 代码是否兼容最低支持版本 - [ ] 是否处理了资源释放和异常断开 - [ ] 是否有硬编码尺寸或坐标这里的“验证清单”是我很推荐的一个设计等于逼 AI 在输出答案前做一遍自检。实测下来加了清单之后AI 的答案明显更稳重复犯低级错误的概率低了很多。5.3 用回归问答集做迭代别靠感觉调Skill 写完之后最好的调试方式不是“我问一次看看效果”而是准备一套固定的回归问题集。把 AI 经常答错的问题整理成 10 到 20 个每个问题都标注“期望出现的 API”和“禁止出现的错误”。每次修改 Skill 后把整套问题重新跑一遍比较结果的变化。比如我整理过这样几条Q1: 外接显示器如何创建新窗口 期望: UIWindowScene session.role .windowExternalDisplay 禁止: UIWindow(frame: UIScreen.main.bounds) Q2: 外接屏断开了怎么处理 期望: UIScreen.didDisconnectNotification / Scene 销毁回调 禁止: 只写 viewWillDisappear Q3: 多窗口之间怎么同步数据 期望: 单一数据源 / ObservableObject / Store 禁止: 各自持有副本这套回归集最大的价值是防止“改了东墙拆了西墙”。今天你修了一个 API 描述错误可能明天 AI 就在另一个问题上开始胡说八道。没有回归集你根本发现不了这种退化。6. 常见问题与排查技巧实录6.1 问题速查表我在实际使用过程中遇到过不少问题整理成一张速查表供大家参考现象常见原因解决办法AI 完全不提外接屏知识Skill 所在路径不对或 description 没有触发检查目录是否在.claude/skills下重新描述触发场景回答里还是旧 API知识文档内容过时或 AI 没读取 references更新文档加入“禁止使用旧方案”的硬规则无论什么问题都触发 Skilldescription 边界写得太宽在描述末尾加“不处理 XX 问题”回答被截断缺少关键步骤知识文档太长超出上下文窗口拆分文档控制在 200 行以内把核心规则放 SKILL.md同一个 Skill 在不同助手上表现差异大各家对 Skill 的解析精度不同以 Claude Code 为基准调试其他助手只做兼容Skill 不生效但路径没错需要重启 AI 会话让配置重新加载重启会话用测试问题重新验证大多数问题都是“触发”“加载”“内容”三个环节出了岔子。排查时按这个顺序来最快能定位。6.2 踩过几次坑之后我的几条实在建议第一个坑是别在 Skill 里塞过时 API。我自己第一次写多屏知识包时参考了老博客写了UIWindow那套外部屏方案结果 AI 每次生成的都是坑排查到怀疑人生。后来我把 iOS 13 的 Scene 生命周期相关文档全部重写才算真正好起来。做 Skill 一定要用最新官方文档做底稿二手资料只当辅助。第二个坑是知识文档不要写长篇大论。AI 的上下文窗口是宝贵的你塞一个 500 行的文档进去它可能读不完就截断了。最优实践是每个文件控制在 100 到 150 行只写结论、代码片段、注意点不要写背景故事。背景和推导过程应该写在博文或教程里而不是塞给 AI。第三个坑是不要期望一个 Skill 解决所有问题。iPhone Duo 开发本身横跨场景生命周期、外接屏、自适应布局、多窗口状态管理好几个子领域指望一个 SKILL.md 全包不现实。这个开源项目拆了五个 references 文件每个文件解决一个子域AI 按需加载效果远好于一个大杂烩。踩过几次坑之后我的体会是这种“领域知识包 提示词约束 回归测试”的组合比单纯在 prompt 里写一百句“你要懂外接屏”都管用。开源 Skill 给 AI 的其实不是答案而是解决一类问题时必须遵循的方法论。把它装进自己的 AI 助手再按自己团队的工程习惯改一改你就能拥有一个真正懂 iPhone 多屏开发的专属助手。最后再分享一个小技巧如果你给这个 Skill 加一个scripts/check_deprecated_api.py让 AI 在生成完代码后自动扫一遍废弃 API效果会再上一个台阶。