Files
ios-client/CLAUDE.md
2026-09-15 14:35:52 +08:00

4.8 KiB
Raw Blame History

CLAUDE.md — iOS 客户端项目 AI 协作规范

项目概览

SwiftUI + MVVM 单向数据流 + SPM 多 target 模块化的 iOS「打卡/计划管理」客户端,功能对齐 wechat-clock-mini(小程序,生产参照)与 android-client(Android 端,原生简化参照)。架构对齐 Android NIA(core/* + feature/*)。

四个主入口 Tab(顺序):首页 / 打卡 / 计划 / 我的;另有独立登录页(手机号 + 短信验证码)与提交计划页(计划 Tab 内推入)。

目录结构

  • ios-client.xcodeproj / ios-client/:App 宿主(薄壳,只含 @main 挂载 AppRootView)
  • IosClientKit/:本地 SPM 包,承载所有模块
    • Sources/App:组合根(AppContainer DI + AppRootView 导航)
    • Sources/CoreModel:领域模型(Sendable 值类型,叶子)
    • Sources/CoreCommon:通用工具(叶子)
    • Sources/CoreDomain:Repository 协议 + UseCase(纯 Swift,不 import SwiftUI)
    • Sources/CoreRepository:Repository 实现(Fake + 未来 OfflineFirst)
    • Sources/CoreNetwork:DTO + APIClient(URLSession)
    • Sources/CoreDatabase:SwiftData(@Model + ModelContainer)
    • Sources/DesignSystem:设计 tokens
    • Sources/CoreUI:可复用 SwiftUI 组件
    • Sources/FeatureHome:首页(落地页:Hero + 模块卡 + 产品介绍)
    • Sources/FeatureCheckin:打卡(状态卡 + 状态 pill + 小组/个人记录)
    • Sources/FeaturePlan:计划(周/月/年 + 小组统计 + 提交计划页)
    • Sources/FeatureProfile:我的(资料 + 小组分组 + 退出登录)
    • Sources/FeatureAuth:登录(手机号 + 短信验证码 + 60s 倒计时)

依赖方向(硬约束,违反即编译不过)

单向无环:App → feature → core;App 额外 → CoreRepository(装配具体实现)。

  • 领域模型只在 CoreModel,其余模块只能 import CoreModel。
  • Repository 协议只定义在 CoreDomain,实现在 CoreRepository。
  • CoreDomain 纯 Swift:禁止 import SwiftUI / 数据框架。
  • DTO 只在 CoreNetwork,领域 Model 只在 CoreModel,二者分离。
  • 禁止命名任何模块为 CoreData(与苹果 CoreData 框架撞名,已统一为 CoreRepository)。

状态管理约定

  • ViewModel:@MainActor @Observable final class,持有 uiState。
  • UiState:enum 关联值(对应 Kotlin sealed interface)。
  • Kotlin → Swift 映射:
Android (Kotlin) iOS (Swift)
Flow<T> AsyncThrowingStream<T, Error>
StateFlow + stateIn @Observable + @MainActor
flatMapLatest Task 取消自动 switch-to-latest
sealed interface UiState enum UiState(关联值)
Hilt @Inject / AppContainer 手写 AppContainer
Retrofit + kotlinx.serialization URLSession + Codable
Room SwiftData
DataStore(会话持久化) Combine CurrentValueSubject(进程内 Fake 会话)

会话 / 登录态

  • SessionRepository 协议(CoreDomain)+ FakeSessionRepository(CoreRepository,final class + Combine CurrentValueSubject<Bool, Never>,默认未登录,AppContainer 持单例共享)。
  • 登录态驱动页面:HomeViewModel 双源切换(已登录 observeHome() / 游客 observeGuestHome());checkin/plan/profile 四态含 loggedOut。
  • flatMapLatest 的 iOS 等价:外层 Task 观察 observeIsLoggedIn(),登录态变化时取消内层数据 Task 并重新订阅。
  • 登录 mock 凭据:手机号 13812341234 + 验证码 123456。

代码风格

  • 跨模块符号一律 public,并加 /// 文档注释。
  • 领域模型标记 Sendable。
  • 命名:类型 PascalCase,变量/函数 camelCase;UI 文案与注释可用中文。

明确禁止

  • ❌ TCA、Swinject 等 DI 框架、Moya 等网络封装、任何第三方大框架
  • ❌ UIKit(除非 SwiftUI 确无法覆盖的极少数场景)
  • ❌ 循环依赖 / 反向 import

构建 / 验证命令

# 编译包(同时做依赖环检测,SPM 遇环即报错)
swift build --package-path IosClientKit

# 模拟器编译 App
xcodebuild -project ios-client.xcodeproj -scheme ios-client \
  -destination 'generic/platform=iOS Simulator' \
  CODE_SIGNING_ALLOWED=NO build

# Lint
swiftlint lint --strict

新增 Feature 清单

  1. 在 IosClientKit/Package.swift 的 targets 加 FeatureXxx 及依赖。
  2. 新建 Sources/FeatureXxx/:Screen + ViewModel + UiState(enum)。
  3. UseCase 放 CoreDomain,Repository 实现放 CoreRepository。
  4. 在 App 的 AppContainer 装配依赖、AppRootView 接入导航。

文档地图

主题 文档
架构与数据流 docs/architecture.md
工作状态与遗留项 docs/progress.md
贡献指南 CONTRIBUTING.md