SwiftUI线程1:致命错误:每个布局项只能出现一次
这个小的代码是从2列与API的文章scrollview
上ArticleView
。不幸的是,在第 6loadMoreContentIfNeeded
次之后,这个错误让我很难受
线程 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()
}
}
回答
我只能指出您的问题,因为仍然缺少一些相关代码。
问题在于您的 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”,它会正常工作。