如何让SwiftUI预览支持ViewModel的多状态测试?
SwiftUI BookmarksView 多状态预览方案
核心思路
通过给BookmarksViewModel添加支持初始数据注入的构造方法,在预览中分别传入空数据和模拟内容数据,实现两种状态的同时预览。
步骤1:改造ViewModel,支持初始数据注入
让ViewModel的构造器接收可选的初始书签数组,默认是空数组,既不影响正常业务逻辑,又能满足预览需求:
class BookmarksViewModel: ObservableObject { @Published var bookmarks: [Bookmark] init(bookmarks: [Bookmark] = []) { self.bookmarks = bookmarks } // 你的其他业务逻辑代码... }
步骤2:调整BookmarksView,接收外部传入的ViewModel
避免在View内部直接初始化ViewModel,改为通过参数接收,提升灵活性:
struct BookmarksView: View { @ObservedObject var viewModel: BookmarksViewModel var body: some View { List(viewModel.bookmarks) { bookmark in Text(bookmark.title) } .overlay { if viewModel.bookmarks.isEmpty { Text("暂无书签") } } } }
步骤3:在PreviewProvider中同时展示两种状态
使用Group将两个预览实例分组,配合previewDisplayName给每个状态命名,方便在画布中区分:
struct BookmarksView_Previews: PreviewProvider { static var previews: some View { Group { // 空状态预览 BookmarksView(viewModel: BookmarksViewModel(bookmarks: [])) .previewDisplayName("Empty State") // 有内容状态预览 let sampleBookmarks = [ Bookmark(id: UUID(), title: "SwiftUI 入门指南"), Bookmark(id: UUID(), title: "Combine 响应式编程"), Bookmark(id: UUID(), title: "iOS 性能优化技巧") ] BookmarksView(viewModel: BookmarksViewModel(bookmarks: sampleBookmarks)) .previewDisplayName("Content State") } } } // 示例Bookmark模型(如果你的项目中已有,可忽略) struct Bookmark: Identifiable { let id: UUID let title: String }
额外提示
- 如果你的ViewModel依赖其他服务(比如网络请求、本地存储),可以进一步抽象为协议,预览时传入模拟实现,实现更复杂的状态测试。
- 可以结合
PreviewDevice给不同状态指定测试设备,覆盖更多场景。
内容的提问来源于stack exchange,提问作者Lorenzo B
相关产品推荐
相关产品推荐

