这个小代码显示了来自 API 的文章,其中有 2 列带有scrollview
on 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()
}
}