返回顶部
f

fosmvvm-viewmodel-generatorFOSMVVM视图模型生成器

Generate FOSMVVM ViewModels for SwiftUI screens, pages, and components. Scaffolds RequestableViewModel, localization bindings, and stub factories.

作者: admin | 来源: ClawHub
源自
ClawHub
版本
V 2.0.6
安全检测
已通过
673
下载量
免费
免费
2
收藏
概述
安装方式
版本历史

fosmvvm-viewmodel-generator

FOSMVVM ViewModel 生成器

按照 FOSMVVM 架构模式生成 ViewModel。

概念基础

完整架构上下文,请参阅 FOSMVVMArchitecture.md | OpenClaw 参考

ViewModel 是 Model-View-ViewModel 架构中的桥梁:

┌─────────────┐ ┌─────────────────┐ ┌─────────────┐
│ Model │ ───► │ ViewModel │ ───► │ View │
│ (数据) │ │ (桥梁) │ │ (SwiftUI) │
└─────────────┘ └─────────────────┘ └─────────────┘

关键洞察: 在 FOSMVVM 中,ViewModel:

  • - 由工厂创建(服务端或客户端)
  • 在编码时本地化(解析所有 @LocalizedString 引用)
  • 由视图消费,视图仅渲染本地化后的数据



首要决策:托管模式

这是每个 ViewModel 的独立决策。 一个应用可以混合使用两种模式——例如,一个带有基于服务端登录的独立 iPhone 应用。

关键问题:这个 ViewModel 的数据来自哪里?

数据来源托管模式工厂
服务端/数据库服务端托管手写
本地状态/偏好设置
客户端托管 | 宏生成 |
| ResponseError(捕获的错误) | 客户端托管 | 宏生成 |

服务端托管模式

当数据来自服务端时:

  • - 工厂在服务端手写(ViewModelFactory 协议)
  • 工厂查询数据库,构建 ViewModel
  • 服务端在 JSON 编码时进行本地化
  • 客户端接收完全本地化的 ViewModel

示例: 登录界面、来自 API 的用户资料、带有服务端数据的仪表盘

客户端托管模式

当数据位于设备本地时:

  • - 使用 @ViewModel(options: [.clientHostedFactory])
  • 宏从初始化参数自动生成工厂
  • 客户端打包 YAML 资源
  • 客户端在编码时进行本地化

示例: 设置界面、引导页、离线优先功能、错误显示

错误显示模式

错误显示是典型的客户端托管场景。你已经从 ResponseError 获取了数据——只需将其包装到针对该错误的特定 ViewModel 中:

swift
// 针对 MoveIdeaRequest 错误的特定 ViewModel
@ViewModel(options: [.clientHostedFactory])
struct MoveIdeaErrorViewModel {
let message: LocalizableString
let errorCode: String

public var vmId = ViewModelId()

// 接收特定的 ResponseError
init(responseError: MoveIdeaRequest.ResponseError) {
self.message = responseError.message
self.errorCode = responseError.code.rawValue
}
}

使用方式:
swift
catch let error as MoveIdeaRequest.ResponseError {
let vm = MoveIdeaErrorViewModel(responseError: error)
return try await req.view.render(Shared/ToastView, vm)
}

每个错误场景都有其自己的 ViewModel:

  • - MoveIdeaErrorViewModel 对应 MoveIdeaRequest.ResponseError
  • CreateIdeaErrorViewModel 对应 CreateIdeaRequest.ResponseError
  • SettingsValidationErrorViewModel 对应设置表单错误

不要创建通用的 ToastViewModel 或 ErrorViewModel——那是统一错误架构,我们避免这样做。

关键洞察:

  • - 无需服务端请求——你已经捕获了错误
  • ResponseError 中的 LocalizableString 属性已经本地化(服务端已完成)
  • 标准的 ViewModel → 视图编码链能正确处理此情况;已本地化的字符串原样传递
  • 客户端托管的 ViewModel 包装现有数据;宏生成工厂

混合应用

许多应用同时使用两种模式:

┌───────────────────────────────────────────────┐
│ iPhone 应用 │
├───────────────────────────────────────────────┤
│ SettingsViewModel → 客户端托管 │
│ OnboardingViewModel → 客户端托管 │
│ MoveIdeaErrorViewModel → 客户端托管 │ ← 错误显示
│ SignInViewModel → 服务端托管 │
│ UserProfileViewModel → 服务端托管 │
└───────────────────────────────────────────────┘

相同的 ViewModel 模式在两种模式下都适用——只有工厂创建方式不同。

核心职责:数据塑形

ViewModel 的职责是为展示塑形数据。这发生在两个地方:

  1. 1. 工厂——需要什么数据,如何转换
  2. 本地化——如何在上下文中呈现(包括区域感知排序)

视图仅负责渲染——它绝不应组合、格式化或重新排序 ViewModel 的属性。

ViewModel 包含的内容

ViewModel 回答:视图需要显示什么?

内容类型表示方式示例
静态 UI 文本@LocalizedString页面标题、按钮标签(固定文本)
动态枚举值
LocalizableString(存储) | 状态/状态显示(参见枚举本地化模式) |
| 文本中的动态数据 | @LocalizedSubs | 欢迎,%{name}! 带替换 |
| 组合文本 | @LocalizedCompoundString | 由片段组成的全名(区域感知顺序) |
| 格式化日期 | LocalizableDate | createdAt: LocalizableDate |
| 格式化数字 | LocalizableInt | totalCount: LocalizableInt |
| 动态数据 | 普通属性 | content: String,count: Int |
| 嵌套组件 | 子 ViewModel | cards: [CardViewModel] |

ViewModel 不包含的内容

  • - 数据库关系(@Parent,@Siblings)
  • 业务逻辑或验证(这些在 Fields 协议中)
  • 暴露给模板的原始数据库 ID(使用类型化属性)
  • 视图必须查找的未本地化字符串

反模式:在视图中组合

swift
// ❌ 错误 - 视图在组合
Text(viewModel.firstName) + Text( ) + Text(viewModel.lastName)

// ✅ 正确 - ViewModel 提供塑形后的结果
Text(viewModel.fullName) // 通过 @LocalizedCompoundString

如果在视图中看到 + 或字符串插值,塑形工作应属于 ViewModel。

ViewModel 协议层级

swift
public protocol ViewModel: ServerRequestBody, RetrievablePropertyNames, Identifiable, Stubbable {
var vmId: ViewModelId { get }
}

public protocol RequestableViewModel: ViewModel {
associatedtype Request: ViewModelRequest
}

ViewModel 提供:

  • - ServerRequestBody - 可通过 HTTP 以 JSON 形式发送
  • RetrievablePropertyNames - 启用 @LocalizedString 绑定(通过 @ViewModel 宏)
  • Identifiable - 为 SwiftUI 提供 vmId 标识
  • Stubbable - 提供 stub() 用于测试/预览

RequestableViewModel 额外提供:

  • - 关联的 Request 类型,用于从服务端获取数据

两类 ViewModel

1. 顶层(RequestableViewModel)

代表完整页面或界面。具有:

  • - 关联的 ViewModelRequest 类型
  • 从数据库构建它的 ViewModelFactory
  • 嵌入其中的子 ViewModel

swift
@ViewModel
public struct DashboardViewModel: RequestableViewModel {
public typealias Request = DashboardRequest

@LocalizedString public var pageTitle
public let cards: [CardViewModel] // 子组件
public var vmId: ViewModelId = .init()
}

2. 子级(普通 ViewModel)

由其父级工厂构建的嵌套组件。无需 Request 类型。

swift
@ViewModel
public struct CardViewModel: Codable, Sendable {
public let id: ModelIdType
public let title: String
public let createdAt: LocalizableDate
public var vmId: ViewModelId = .init()
}



展示型与表单型 ViewModel

ViewModel 服务于两个不同的目的:

目的ViewModel 类型采用 Fields?
展示数据(只读)展示型 ViewModel
收集用户输入(可编辑)
表单型 ViewModel | 是 |

展示型 ViewModel

用于显示数据——卡片、行、列表、详情视图:

swift
@ViewModel
public struct UserCardViewModel {
public

标签

skill ai

通过对话安装

该技能支持在以下平台通过对话安装:

OpenClaw WorkBuddy QClaw Kimi Claude

方式一:安装 SkillHub 和技能

帮我安装 SkillHub 和 fosmvvm-viewmodel-generator-1776420040 技能

方式二:设置 SkillHub 为优先技能安装源

设置 SkillHub 为我的优先技能安装源,然后帮我安装 fosmvvm-viewmodel-generator-1776420040 技能

通过命令行安装

skillhub install fosmvvm-viewmodel-generator-1776420040

下载

⬇ 下载 fosmvvm-viewmodel-generator v2.0.6(免费)

文件大小: 13.9 KB | 发布时间: 2026-4-17 18:41

v2.0.6 最新 2026-4-17 18:41
Initial ClawHub release

Archiver·手机版·闲社网·闲社论坛·羊毛社区· 多链控股集团有限公司 · 苏ICP备2025199260号-1

Powered by Discuz! X5.0   © 2024-2025 闲社网·线报更新论坛·羊毛分享社区·http://xianshe.com

p2p_official_large
返回顶部