You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI预览无法加载Mock JSON数据问题求助

解决SwiftUI预览无法加载Mock JSON数据的问题

问题根源

你的PostListView通过@StateObject private var viewModel = PostViewModel(service: PostService())硬编码初始化了使用真实API服务的ViewModel,@StateObject的优先级高于environmentObject,所以预览中通过.environmentObject(viewModel)传入的Mock版本会被忽略,导致预览仍然调用真实API。

解决方案:依赖注入重构

通过让PostListView接收外部传入的ViewModel,实现服务的灵活替换,既不影响正常运行,也能让预览使用Mock服务。

步骤1:修改PostListView,支持ViewModel注入

将硬编码的@StateObject改为@ObservedObject,并提供接收ViewModel的初始化方法:

struct PostListView: View {
    @ObservedObject var viewModel: PostViewModel // 改为外部传入

    // 提供默认初始化,保证正常运行时默认使用真实服务
    init(viewModel: PostViewModel = PostViewModel(service: PostService())) {
        self.viewModel = viewModel
    }

    var body: some View {
        NavigationView {
            VStack {
                if viewModel.isLoading {
                    ProgressView()
                } else if !viewModel.errorMessage.isEmpty {
                    Text(viewModel.errorMessage)
                } else {
                    List(viewModel.posts) { post in
                        VStack(alignment: .leading) {
                            Text(post.title)
                                .font(.headline)
                            Text(post.body)
                                .font(.subheadline)
                                .foregroundColor(.gray)
                        }
                    }
                }
            }
            .navigationTitle("Posts")
        }
    }
}

步骤2:更新预览代码,传入Mock ViewModel

直接初始化使用MockPostService的ViewModel并传入PostListView:

struct PostListView_Previews: PreviewProvider {
    static var previews: some View {
        PostListView(viewModel: PostViewModel(service: MockPostService()))
    }
}

可选优化:保留@StateObject的生命周期管理

如果希望保持ViewModel的生命周期由View管理(比如在导航栈中维持状态),可以保留@StateObject,通过重载初始化方法区分环境:

struct PostListView: View {
    @StateObject private var viewModel: PostViewModel

    // 正常运行时的初始化
    init() {
        _viewModel = StateObject(wrappedValue: PostViewModel(service: PostService()))
    }

    // 预览/测试专用初始化
    init(mockViewModel: PostViewModel) {
        _viewModel = StateObject(wrappedValue: mockViewModel)
    }

    // body部分保持不变...
}

// 预览代码
struct PostListView_Previews: PreviewProvider {
    static var previews: some View {
        PostListView(mockViewModel: PostViewModel(service: MockPostService()))
    }
}

额外注意事项

  • 确认SamplePost.json已添加到预览目标的资源中(在Xcode选中文件,右侧检查器确认"Target Membership"包含预览目标)
  • MockPostService的fetchData方法同时标记了async和使用completion回调,建议统一风格:要么用async/await,要么用completion,避免混合逻辑引发潜在问题

内容的提问来源于stack exchange,提问作者Shourob Datta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 11:32:42