Files
suixinkan_uikit/AGENTS.md
汉秋 39a9038a3b Switch default actor isolation to nonisolated and document concurrency conventions.
Align app and test targets on nonisolated defaults so ViewModels stay off MainActor by default, and capture the resulting patterns in AGENTS.md.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-06 16:18:20 +08:00

4.6 KiB
Raw Blame History

suixinkan

项目概览

Swift + UIKit 工程,MVVM 架构。iOS 版 随心瞰商家版,与 Android ZhiFlyFollow 功能对齐——以 Android 工程为参考同步实现业务能力UI 按 UIKit 习惯编写,不逐行翻译 Compose。

Android 参考: /Users/hanqiu/Desktop/android_project/zhiflyfollowcom.zhifly.follow
文档: CLAUDE.mddocs/home/docs/排队叫号业务流程梳理.md
后端: 生产 api.zhifly.cn,测试 api-test.zhifly.cn

主要功能域: 首页/订单/数据/我的 Tab登录注册与实名认证订单/任务/核销;相册与云存储;直播与钱包;景区排队叫号、位置上报;消息、设置、扫码、语音通话等。

同步约定: 接口与业务流程以 Android NetworkApi / DTO / ViewModel 为准UI 用 SnapKit 独立设计OTG 相机、DJI 飞控、厂商推送等 Android 专属能力按需评估。

平台与设备

iOS 16+ · 仅 iPhone · 仅竖屏。不做 iPad / 横屏 / 低版本 API 适配。

架构MVVM

层级 职责
View UIViewController / 自定义 UIViewUI 展示与交互,不含业务逻辑
ViewModel 业务逻辑与状态通过方法、delegate 或明确回调与 View 通信
Model 数据模型、网络/本地数据源
  • 新增功能:对应 Model + ViewModel + ViewController同步单元测试
  • ViewModel 不依赖 UIKit 视图类型

开发风格

命令式 UIKit,不用 @Observable / ObservableObject / @Published、不用 Combine 驱动 UI、不堆泛化 onChanged 回调。

  • 在明确时机(点击、网络回调、页面出现)主动刷新 UIapply(snapshot) 或更新子视图)
  • 通信用 delegate、target-action 或语义明确的单一回调
  • 对照 Android 行为 用 UIKit 重写,不翻译 Compose 语法
  • ViewModel 属性供读取UI 更新由 View 在回调中主动触发

Swift 并发与 Actor

工程 Default Actor Isolation 配置为 nonisolatedsuixinkansuixinkanTests 均为 SWIFT_DEFAULT_ACTOR_ISOLATION = nonisolated)。新类型默认不隐式绑定 @MainActor,与命令式 UIKit + 显式刷新风格一致。

Target Default Actor Isolation
suixinkan nonisolated
suixinkanTests nonisolated

编写约定:

  • ViewModel / Model:保持 nonisolated,不依赖默认 MainActor纯逻辑与校验可用 nonisolated static
  • 需要主线程的类型:在类型上显式标注 @MainActor(如 APIClientAuthAPIProfileAPINetworkServicesOSSUploadServiceAppRouter)。
  • UI 更新:在 UIViewController 内通过 Task { @MainActor in ... } 或已在主线程的回调中刷新 UI不假设 ViewModel 调用方一定在主 ActoronStateChange 回调应切回主线程再改 UI。
  • 网络与可发送类型:请求/环境等跨边界类型保持 nonisolated + Sendable(如 APIRequest),避免无意引入 actor 隔离冲突。
  • 单元测试target 默认为 nonisolatedMockURLSession 等替身保持 nonisolated。需要构造 @MainActor 类型(APIClientAuthAPI 等)的测试类应显式标 @MainActor

新增代码不要为「凑隔离」给 ViewModel 或普通 model 加 @MainActor;仅 UI 入口、共享网络单例等确需主线程协调处显式标注。

代码注释

class / struct / enum、协议及公开 API 必须写 /// 文档注释,说明职责与用途;复杂内部逻辑按需补充。不写废话注释、不写过时注释。

技术栈与库

Swift · UIKit · SnapKit代码布局约束写在 setupUI() / setupConstraints())· Kingfisherkf.setImage(with:) 加载网络图,列表利用缓存)

列表展示

  • 简单列表 → UITableView;复杂列表(网格、卡片、不等高)→ UICollectionView + Compositional Layout
  • 数据更新用 Diffable Data Source + apply(_:animatingDifferences: true)Item 遵循 Hashable,避免 reloadData()
  • ViewModel 提供数据View 构建 snapshot 并 apply

单元测试

每增一功能必须附带单元测试且全部通过(Cmd + U / xcodebuild test),与功能同次提交。

层级 优先级
ViewModel / Model 优先
View 按需

测试放 suixinkanTests/独立可重复mock 网络与外部依赖。

开发注意

  • SnapKit 布局、Kingfisher 图片、Diffable 列表带动画
  • 以 Android 工程为功能参考,命令式 UIKit不用 Observable / Combine
  • 新增功能必测、类型与公开 API 必注释、保持简洁