SwiftUI 多模态 AI 教程:图片输入、动态配置与模型切换
下面的结构面向 Xcode 27 与 iOS 27 beta。目标不是把完整 Agent 塞进一个 SwiftUI View,而是建立四个边界:界面选择图片,预处理器产生受控 attachment,模型策略选择可用后端,session service 负责生成与取消。这样 beta API 变化被限制在服务层。
状态只描述界面事实
ViewModel 可以有 idle、preparing、generating、result 与 failure,并保存所选图片、任务 id 和可取消 Task。View 不持有 session,也不直接访问 provider 凭据。用户更换图片或离开页面时取消旧任务,新的结果只有在 task id 仍匹配时才提交,避免晚到响应覆盖界面。
图片加载后先修正方向、限制极端像素尺寸、移除不需要的元数据,并在压缩前保留适合任务的细节。Apple 允许多种尺寸与比例,但大图会增加 token 和延迟;这不是要求固定裁剪,而是要求用真实照片评测质量与资源。
模型策略显式选择
定义自己的用途,例如 privateQuickLook、deepReasoning 和 approvedProvider。策略检查系统版本、模型 availability、vision capability、网络与组织设置,再返回一个 LanguageModel。不要按设备名称硬编码,也不要在设备端不可用时静默把敏感照片上传远端。
如果降级会改变数据路径,界面应解释并让用户选择。Private Cloud Compute、第三方 provider 与本地模型的认证、计费和隐私含义不同。模型切换记录在 trace 中,但下游只接收领域结果。
发送图像与结构化目标
服务把图片 attachment 与清晰文本一起构造 prompt,例如要求“依据图片列出可见物体;不确定就标记 unknown;不要猜测地点或人物身份”。对需要 UI 展示的数据使用版本化 @Generable 领域类型,并在返回后继续验证数组长度、文本限制与敏感类别。
图像可进入工具参数并不意味着工具应该自由调用。OCR、条码或自定义识别工具返回不可信数据;URL 必须走 allowlist,联系人、相册写入和网络上传需要应用授权。模型没有权限绕过系统隐私弹窗。
动态 Profile 与 SwiftUI 依赖注入
Profile 组合指令、工具与配置,适合“菜谱建议”“票据摘录”等不同场景。将其定义为只读、版本化值,由 composition root 注入 ViewModel。预览和单元测试注入 fake service;生产再注入 Foundation Models adapter。
fake service 可以用固定延迟返回结果,并模拟取消、模型不可用、图片损坏、guardrail 和工具失败。测试断言状态转换与晚到结果被丢弃,不需要真实模型或付费调用。
体验与验收
生成期间显示具体阶段与取消按钮,不伪造百分比。VoiceOver 朗读状态变化;错误区分“设备不支持”“模型暂不可用”“图片无法读取”和“内容不能处理”。结果注明由 AI 生成,并给用户编辑或报告入口。
评测集应包含横竖图、截图、小字、低光、多个对象、敏感内容和无关图片。检查事实、遗漏、无根据推断、延迟、内存、取消与数据路径。不同模型用同一领域评分,但允许 provider adapter 使用本地配置。
SwiftUI 多模态功能的难点不是一行 attachment API,而是异步状态、隐私路由和能力差异。把 View、预处理、模型策略与 session service 分开,既能利用 WWDC26 的统一抽象,也不会把 beta 细节扩散到整个应用。