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

SwiftUI中fetchAuthorArticles首次点击无法获取JSON数据的原因排查

分析与解决方案

针对你遇到的「首次点击无法获取JSON数据,关闭Sheet后再次点击正常」的问题,我整理了几个最可能的原因及对应的解决办法:

可能的原因1:onAppear 绑定位置不合理

你当前把数据请求的触发逻辑绑定在了 LazyVGrid 的 onAppear 上,而不是整个视图的根容器(ScrollView)上。在Sheet首次弹出时,LazyVGrid 的渲染可能存在延迟,导致 onAppear 没有被及时触发,进而漏掉了首次的数据请求。

可能的原因2:首次打开Sheet时 selectedAuthor.author_id 未正确赋值

如果Sheet是通过列表点击触发的,可能存在「首次点击时 selectedAuthor 还没完成赋值就弹出Sheet」的情况——此时请求URL中的 authorID 是默认值(比如0),服务器返回空数据;而关闭Sheet后再次打开时,selectedAuthor 已经完成赋值,请求的URL正确,自然能拿到数据。

可能的原因3:AuthorService 中 isLoadingPage 属性未正确声明

从代码里能看到你在 fetchAuthorArticles 中使用了 isLoadingPage,但 AuthorService 类里没有把它声明为 @Published 属性。这不仅会导致编译警告,还会让视图无法感知加载状态的变化,间接影响数据更新的反馈逻辑。


对应的解决方案

1. 调整 onAppear 的绑定位置

把 onAppear 移到 ScrollView 上,确保整个视图出现时就触发数据请求:

struct SelectedAuthorView: View {
    @Binding var selectedAuthor: AuthorPost
    @ObservedObject var service = AuthorService()
    var cellNumber: Int = 0
    let columns: [GridItem] = Array(repeating: GridItem(.flexible(), spacing: 0), count: 2)
    
    var body: some View {
        ScrollView(.vertical, showsIndicators: true) {
            LazyVGrid(columns: columns, spacing: 0) {
                ForEach(Array(service.authorArticles.articles.enumerated()), id: \.1.id) {i, post in
                    AuthorArticleListItem(articlePost: post, cellNumber: i)
                }
                .background(Color(.white))
                if service.isLoadingPage {
                    ProgressView()
                        .padding()
                        .offset(x: UIScreen.main.bounds.width / 4)
                }
            }
        }
        // 将onAppear移到ScrollView根容器上
        .onAppear {
            print("触发请求,authorID: \(selectedAuthor.author_id)") // 打印ID验证是否正确
            self.service.fetchAuthorArticles(authorID: selectedAuthor.author_id)
        }
    }
}

2. 确保 selectedAuthor 完全赋值后再弹出Sheet

如果是通过按钮或列表项触发Sheet,要先完成 selectedAuthor 的赋值,再弹出视图。比如用 sheet(item:) 的正确写法:

struct AuthorListView: View {
    @State private var selectedAuthor: AuthorPost?
    
    var body: some View {
        List(authors) { author in
            Button(action: {
                self.selectedAuthor = author // 先完成赋值
            }) {
                Text(author.author_name)
            }
        }
        .sheet(item: $selectedAuthor) { author in
            SelectedAuthorView(selectedAuthor: .constant(author))
        }
    }
}

3. 完善 AuthorService 的属性声明

给 isLoadingPage 添加 @Published 修饰符,确保视图能感知加载状态的变化:

class AuthorService: ObservableObject {
    @Published var authorArticles = AuthorList(author: Author(author_id: 0, articles: 0, newspaper_image: "", author_name: "", author_image: "", newspaper: ""), articles: [])
    @Published var isLoadingPage = false // 补充@Published声明
    
    func fetchAuthorArticles(authorID: Int){
        isLoadingPage = true
        // 后续请求代码保持不变
    }
}

额外调试建议

在 fetchAuthorArticles 里打印请求参数,确认首次请求的 authorID 和 URL 是否正确:

func fetchAuthorArticles(authorID: Int){
    isLoadingPage = true
    print("当前请求的authorID: \(authorID)")
    let urlString = "http://author/article/list/\(authorID)/"
    print("请求URL: \(urlString)")
    if let selectedAuthorUrl = URL(string:urlString) {
        // 后续请求代码保持不变
    }
}

通过这些步骤,应该能定位并解决首次点击无法获取数据的问题。

内容的提问来源于stack exchange,提问作者Mert Köksal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:30:14