| name | swiftui-standards |
| description | SwiftUI 开发标准规范,包括代码组织、MARK 分组、日志记录、预览代码和事件监听的统一规范。 |
SwiftUI 开发标准规范
本技能确保所有 SwiftUI 代码遵循项目的统一开发规范。
何时使用
- 编写新的 SwiftUI 视图
- 重构现有 Swift 代码
- 实现事件监听
- 添加日志记录
- 组织代码结构
核心规范
1. 代码组织原则
文件组织:
- 每个 struct/class 应该放在独立的文件中
- 文件名应与类型名称保持一致
- 相关组件应组织在同一目录下
- 代码迁移后不添加"已迁移"注释
目录结构:
Core/
├── Events/ # 所有事件相关代码
│ ├── AppEvents.swift
│ └── SettingEvents.swift
├── Bootstrap/
├── Contract/
└── Models/
2. MARK 分组规范
所有 SwiftUI 视图文件必须按以下顺序使用 MARK 分组:
示例模板:
import SwiftUI
struct MyView: View {
@State private var isLoading = false
@State private var items: [String] = []
var body: some View {
List(items, id: \.self) { Text($0) }
.onAppear(perform: handleOnAppear)
}
}
extension MyView {
private var filteredItems: [String] {
items.filter { !$0.isEmpty }
}
}
extension MyView {
func refresh() {
}
}
extension MyView {
@MainActor
func setItems(_ newValue: [String]) {
items = newValue
isLoading = false
}
}
extension MyView {
func handleOnAppear() {
isLoading = true
}
}
#if os(macOS)
#Preview("App - Large") {
ContentView()
.inRootView()
.frame(width: 600, height: 1000)
}
#Preview("App - Small") {
ContentView()
.inRootView()
.frame(width: 600, height: 600)
}
#endif
#if os(iOS)
#Preview("iPhone") {
ContentView()
.inRootView()
}
#endif
3. 日志记录规范
使用 os.Logger 进行日志记录,禁止使用 os_log。 详见 .cursor/rules/swift-log.mdc。
Core 模块使用 AppLogger.core:
struct MyView: View, SuperLog {
nonisolated static let emoji = "🎯"
nonisolated static let verbose = false
func someFunction() {
if Self.verbose {
AppLogger.core.info("\(Self.emoji) Some operation started")
}
AppLogger.core.info("\(Self.emoji) Operation completed")
}
}
Plugin 模块使用插件 logger:
struct MyTool: AgentTool, SuperLog {
nonisolated static let emoji = "🔍"
nonisolated static let verbose = false
func execute() {
if Self.verbose {
MyPlugin.logger.info("\(Self.emoji) Executing tool")
}
}
}
SuperLog 协议要求:
- 实现
nonisolated static let emoji - 独特的 emoji 标识
- 实现
nonisolated static let verbose - 详细日志控制
- 日志消息中可包含
\(Self.emoji) 作为前缀
日志级别:
AppLogger.core.info("\(Self.emoji) Important operation completed")
if Self.verbose {
AppLogger.core.info("\(Self.emoji) Detailed debug information")
}
AppLogger.core.error("Operation failed: \(error.localizedDescription)")
AppLogger.core.warning("Using fallback configuration")
4. 事件监听规范
事件抛出时,必须为 View 扩展添加 onXxx 方法:
extension View {
func onCustomEvent(perform action: @escaping () -> Void) -> some View {
self.onReceive(NotificationCenter.default.publisher(for: .customEvent)) { _ in
action()
}
}
}
.onCustomEvent(perform: handleEvent)
func handleEvent() {
}
事件文件组织:
- 所有事件扩展放在
Core/Events/ 目录
AppEvents.swift - 应用生命周期事件
SettingEvents.swift - 设置相关事件
5. 预览代码规范
每个 Swift 文件底部必须添加多尺寸预览:
#if os(macOS)
#Preview("App - Large") {
ContentView()
.inRootView()
.frame(width: 600, height: 1000)
}
#Preview("App - Small") {
ContentView()
.inRootView()
.frame(width: 600, height: 600)
}
#endif
#if os(iOS)
#Preview("iPhone") {
ContentView()
.inRootView()
}
#endif
Emoji 选择指南
UI 相关
🌿 - View 组件
📱 - 移动端
🖥️ - 桌面端
🎛️ - 控制面板
📋 - 表单组件
数据相关
🏠 - 数据提供者
💾 - 数据存储
📊 - 数据分析
🔄 - 数据同步
业务功能
🔧 - 工具类
📁 - 文件管理
🌳 - 项目管理
📝 - 文本编辑
🔍 - 搜索功能
系统相关
🍎 - macOS
⚙️ - 系统配置
🔗 - 网络连接
🔔 - 通知系统
最佳实践
代码组织
- ✅ 使用 extension 隔离不同分组
- ✅ 保持 MARK 分组顺序统一
- ✅ 语义化命名:
onXxx / handleXxx
- ✅ 状态更新集中在 Setter 分组
日志记录
- ✅ 使用
os.Logger(AppLogger.core 或 PluginName.logger),禁止 os_log
- ✅ 使用
import os,禁止 import OSLog
- ✅ 使用 verbose 控制调试级别
- ✅ 避免记录敏感信息
- ✅ 通过 subsystem/category 过滤:
log stream --predicate 'subsystem == "com.coffic.lumi"'
事件处理
- ✅ 使用
perform: 语法一行完成
- ✅ 事件扩展放在
Core/Events/ 目录
- ✅ 确保方法名唯一
- ✅ 注意线程安全和内存管理
预览代码
- ✅ 提供多种尺寸预览
- ✅ 使用条件编译适配平台
- ✅ 使用
inRootView() 包装
注意事项
- 文件迁移:迁移代码后不添加"已迁移"注释
- 命名冲突:确保
onXxx 方法名在项目中唯一
- 线程安全:UI 更新操作使用
@MainActor
- 内存管理:避免事件监听中的循环引用
- 日志过滤:利用 Console.app 或
log stream 按 subsystem、category 过滤
遵循此规范可以显著提升代码的可读性、可维护性和开发体验。