
别让锁屏小组件暴露余额:用 AI + SwiftUI privacySensitive 标记敏感内容
这一技教你先把 widget 字段分成公开与敏感两类,再让 AI 用 SwiftUI privacySensitive 标记余额、金额和账号信息,并在真实锁屏场景中独立验收遮罩范围。
锁屏小组件的问题,不只是显示不显示
余额、订单金额、会员等级这类内容放进 iOS 小组件后,用户可能在锁屏上看到它。产品通常希望小组件仍然有用,但不希望路人一眼读出具体金额。这个决定应该在写代码前完成:哪些信息可以公开,哪些信息在隐私敏感的展示环境里要遮住。
SwiftUI 的
privacySensitive(_:) 是一个视图修饰符,Apple 对它的定义是「标记视图含有敏感、私密的用户数据」。Apple 在 WWDC21 的 widget 示例中,用 .privacySensitive() 标记账户余额;当 widget 出现在 Lock Screen 等隐私敏感展示环境时,系统可以对这部分内容进行隐私遮罩。1 2这条信息的边界也很重要:本期只讲「widget 在锁屏场景下如何标记敏感字段」。它不是服务端权限、日志治理或所有截图和录屏场景的替代方案。
先写公开字段和敏感字段表
不要先对整个 widget 加一层遮罩。先列出锁屏状态下每个字段应该呈现什么:
| widget 字段 | 锁屏时的产品规则 | 为什么 |
|---|---|---|
| 产品名、功能名 | 保留 | 用户仍要知道这是哪个 widget |
| 「有一笔待处理订单」 | 只有在不暴露身份和金额时保留 | 这句话可能只是状态,也可能泄露业务信息 |
| 余额、订单金额、积分总数 | 遮罩 | 具体数值通常属于个人数据 |
| 用户名、卡号尾号、地址片段 | 遮罩或删除 | 拼接后可能暴露身份 |
| 「打开 App 查看」 | 按产品规则保留 | 它本身不应带出敏感值 |
表里最容易漏的是「组合文本」。例如
余额 ¥128.45 是一条 Text,不能只给数字变量加标记后,又在另一个公开 Text 里重复显示金额。字段表要对应最终画面上的每一处文本,而不是只对应数据模型里的一个属性。让 AI 只改 widget 的敏感 Text
在 Xcode 里找到 widget 的入口视图,先保存当前版本。把字段表和下面的指令一起交给 AI 编码工具:
请只修改当前 widget 的入口视图,不要重写 timeline、数据请求、Entry 模型、App Intent 或布局结构。根据这张规则表处理敏感内容:产品名和「打开 App 查看」保留;余额、订单金额、积分总数、用户名和卡号尾号标记为敏感。只给最终显示敏感数据的 SwiftUI 视图加.privacySensitive(),不要把整个 widget 容器一起标记,除非规则表明确要求整块内容都遮罩。如果金额已经被拼接进一段公开文案,请先列出这处重复显示的位置,再给出最小修改。不要改变数据来源、缓存、刷新频率或未涉及的公开文案。输出:修改了哪些视图、哪些字段被标记、哪些字段仍然公开,以及我如何在真实锁屏 widget 上验收。
这样约束 AI 有两个好处。第一,改动范围停在展示层,PM 可以直接对比差异。第二,AI 必须回答「哪些字段仍然公开」,不容易把「整个 widget 看起来安全」误当成「敏感数据都被处理了」。
最小实现可以是下面这样:
struct AccountWidgetEntryView: View {
let balanceText: String
var body: some View {
VStack(alignment: .leading) {
Text("账户概览")
.font(.caption)
Text(balanceText)
.privacySensitive()
.font(.title2)
Text("打开 App 查看")
.font(.caption2)
}
}
}这里的关键不是变量名,而是标记贴在最终显示余额的
Text 上。Apple 的 WWDC 示例也提醒了一个范围问题:privacySensitive 可以加在容器视图上;如果加在 VStack 这类容器上,容器里的内容会一起被遮罩。需要保留公开字段时,就不要为了省事把修饰符贴到最外层。2如果你的 widget 使用一行组合文案,例如「余额 ¥128.45」,优先让 AI 把敏感值拆成独立的 Text,再标记它;如果拆分会改变现有布局,就让 AI 先说明差异,不要直接重写整个 widget。
用真实锁屏场景验收
Preview 能帮你看布局,但它不能代替锁屏隐私场景的验收。至少准备一台能运行该 widget 的 iPhone,按下面顺序检查:
- 解锁状态:添加 widget,确认公开字段和敏感字段都符合产品规则,金额来自当前账号,没有显示旧账号的数据。
- 锁屏状态:锁定设备,再查看同一个 widget。确认余额、金额、用户名等标记字段被系统遮罩,产品名等公开字段仍保留;不要只看 widget 是否还占着一块空白。
- 多个尺寸:分别检查小号、中号和产品实际支持的其他尺寸。确认没有因为窄尺寸改用了另一段未标记的金额文案。
- 组合文案:搜索 widget 代码里所有金额、账号和身份字段的显示位置。检查格式化字符串、辅助说明和无障碍标签里没有重复暴露敏感值。
- 账号切换:退出当前账号或切换账号后重新打开 widget,确认旧余额不会继续显示。这个检查属于数据更新规则,不能靠
privacySensitive代替。 - 遮罩范围:如果整块账户摘要都应该隐藏,把修饰符加在容器上并重新检查;如果只有余额要隐藏,确认产品名和打开入口没有一起消失。
- 其他暴露面:把截图、录屏、通知文案、调试日志和服务端返回权限单独列入缺陷单。不要因为锁屏 widget 已遮罩,就把结论写成「所有隐私场景都已覆盖」。
最容易误判的是第 2 步:在模拟器或 Preview 里看到一个灰色占位,不等于真实设备在锁屏状态下会按你的字段边界展示。系统上下文、widget 尺寸和数据更新都要在实际入口验证。
PM 今天可以独立完成的清单
- 选一个显示余额、金额、积分或账号信息的 iOS widget。
- 把每个可见字段分成「锁屏保留」「锁屏遮罩」「锁屏删除」三类。
- 搜索组合文案和辅助文本,确认敏感值没有在别处重复出现。
- 让 AI 只修改 widget 入口视图,并要求它列出字段覆盖范围。
- 检查
.privacySensitive()是否贴在最终显示敏感内容的视图上。 - 在真实设备的解锁、锁屏、多个尺寸和账号切换场景下验收。
- 把截图、录屏、通知、日志和服务端权限列为独立检查项。
privacySensitive 的价值,是把「这段内容不适合在隐私敏感的 widget 场景中直接展示」变成代码里可检查的标记。先决定锁屏时哪些字段还能说,再让 AI 做局部修改,PM 才能在没有研发协助的情况下判断这次改动是否真的覆盖了风险。Related content
- Sign in to comment.
