2

这个小代码显示了来自 API 的文章,其中有 2 列带有scrollviewon ArticleView。不幸的是,在第 6 次之后loadMoreContentIfNeeded,这个错误让我很难受

线程1:致命错误:每个布局项只能出现一次

我曾尝试添加.id(UUID())我的代码以避免 id 问题,但它也没有帮助。我还观察到这个错误也发生在 LazyVStavk 中。如果您将 LazyVStack 更改为 VStack,则不会出现此问题。但是 SwiftUI 中没有任何东西叫做VGrid.

struct ArticleView: View {
@ObservedObject var service = ArticleService()
let columns: [GridItem] = Array(repeating: GridItem(.flexible(), spacing: 0), count: 2)
var body: some View {     
ScrollView(.vertical, showsIndicators: false) {
                        LazyVGrid(columns: columns, spacing:0) {
                            ForEach(Array(service.articlePost.enumerated()), id: \.1.article_id) { i, post in
                                ArticleListElementView(articlePost: post, cellNumber: i)
                                    .id(UUID())
                                    .onAppear {
                                        self.service.loadMoreContentIfNeeded(currentItem: post)
                                    }
                                    .padding(.all, 20)
                                    .onTapGesture {
                                        self.shown = true
                                        self.selectedArticle = post
                                    }
                               }
                          }
                     }

 private func loadMoreContent() {
    
    guard !isLoadingPage && canLoadMorePages else {
        return
    }
    isLoadingPage = true
    
    let parameters = ["index": "articles", "start" : "\(currentPage)"]
    if let url = URL(string: "http:/v2/search/") {
        let session = URLSession(configuration: .default)
        var request = URLRequest(url:url)
        request.httpMethod = "POST"
        
        do {
            request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
        } catch let error {
            print(error.localizedDescription)
        }
        
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")
        
        session.dataTaskPublisher(for: request as URLRequest)
            .map(\.data)
            .decode(type: ArticleResults.self, decoder: JSONDecoder())
            .receive(on: DispatchQueue.main)
            .handleEvents(receiveOutput: { response in
                self.isLoadingPage = false
                self.currentPage += 1
            })
            .map({ response in
                return self.articlePost + response.articles
            })
            .catch({ _ in Just(self.articlePost) })
            .assign(to: &$articlePost)
    }
    
}

func loadMoreContentIfNeeded(currentItem item: ArticlePost?) {
    guard let item = item else {
        loadMoreContent()
        return
    }
    
    let thresholdIndex = articlePost.index(articlePost.endIndex, offsetBy: -5)
    if articlePost.firstIndex(where: { $0.id == item.id }) == thresholdIndex {
        loadMoreContent()
    }
}
4

1 回答 1

7

我只能指出这个问题,因为仍然缺少一些相关代码。

问题在于您的 ForEach 或您的数组。您正在通过 识别内容id: \.1.article_id。不过,我猜!在您的数组中有具有相同文章 ID 的项目。LazyVGrid要求您的内容具有明确的 unique id,而VStack没有。

由于我不知道您的数组或loadMoreContentIfNeeded函数,我无法指出您的问题,为什么会有重复的项目。

这是一个向您展示差异的示例:

这将崩溃,因为服务包含两次“Test123”并且您通过它们的内容来识别它

struct ContentView: View {
    var service = ["Test123", "Test1235", "Test123", "dasdkjasdkas"]
    let columns: [GridItem] = Array(repeating: GridItem(.flexible(), spacing: 0), count: 2)
    
    var body: some View {
        ScrollView(.vertical, showsIndicators: false) {
            LazyVGrid(columns: columns, spacing:0) {
                ForEach(service, id: \.self) { element in
                    Text(element)
                        .id(UUID())
                        .onAppear {
                            //self.service.loadMoreContentIfNeeded(currentItem: post)
                        }
                        .padding(.all, 20)
                        .onTapGesture {
                            //self.shown = true
                            //self.selectedArticle = post
                        }
                }
            }
        }
    }
}

删除一个“Test123”,它会正常工作。

于 2020-12-16T17:52:16.810 回答