在 SwiftUI 中滚动时,许多项目列表崩溃,我该如何解决?
Posted
技术标签:
【中文标题】在 SwiftUI 中滚动时,许多项目列表崩溃,我该如何解决?【英文标题】:List of a lot of items crash when scrolling in SwiftUI, How can I fix it? 【发布时间】:2021-02-13 10:20:54 【问题描述】:我在 SwiftUI 中有一个简单的项目列表,如下所示:
ForEach((1...50), id: \.self)
Text("\($0)….........")
Text("\($0)….........")
Text("\($0)….........")
Text("\($0)….........")
我在使用更复杂的视图时遇到了同样的问题,但我在这里只用一个文本视图对其进行了简化。它会产生同样的问题
崩溃错误:
2021-02-13 21:03:07.124039+1100 rawateb[1696:71245] [ServicesDaemonManager] interruptionHandler is called. -[FontServicesDaemonManager connection]_block_invoke
2021-02-13 21:03:07.163944+1100 rawateb[1696:71245] XPC connection interrupted
Message from debugger: Terminated due to signal 9
那么,我怎样才能在不崩溃的情况下处理一大堆项目
更新
我的完整代码是
//
// CalendarView.swift
// rawateb
//
// Created by Hatim Hoho on 7/2/21.
//
import SwiftUI
import Combine
import QGrid
struct CalendarView: View
//@ObservedObject var viewModel = CalendarViewModel()
@EnvironmentObject var settings: UserSettings
@Environment(\.verticalSizeClass) var verticalSizeClass: UserInterfaceSizeClass?
@Environment(\.horizontalSizeClass) var horizontalSizeClass: UserInterfaceSizeClass?
@State var saleries = [FutureSalery]()
var body: some View
ScrollView
VStack
GeometryReader geometry in
HStack
Button(action:
print("Button was tapped")
// add new future salery
self.addFutureSalery()
)
Image(systemName: "plus.circle")
.resizable()
.foregroundColor(.blue)
.padding()
.frame(width: 70, height: 70, alignment: .center)
Text("رواتب الأشهر القادمة")
.font(.title2)
.bold()
.multilineTextAlignment(.center)
.foregroundColor(Color("labelColor"))
Button(action:
print("Button was tapped")
self.removeFutureSalery()
)
Image(systemName: "minus.circle")
.resizable()
.foregroundColor(.blue)
.padding()
.frame(width: 70, height: 70, alignment: .center)
.padding([.top, .bottom], 38)
.offset(y: geometry.frame(in: .global).minY > 38 ? -geometry.frame(in: .global).minY+38 : 0)
.frame(width: geometry.size.width)
.blur(radius: -geometry.frame(in: .global).minY * 0.38)
.frame(height: 150)
Spacer()
//List
ForEach((1...50).reversed(), id: \.self)
Text("\($0)….........")
Text("\($0)….........")
Text("\($0)….........")
Text("\($0)….........")
//
// QGrid(self.saleries, columns: 2) salery in
// SaleryCellItem2(salery: salery)
//
// .padding()
struct SaleryCellItem : View
var salery: FutureSalery
var body: some View
GeometryReader(content: geometry in
HStack
Text("\(salery.remainingDays)")
.frame(width: geometry.size.width / 3, height: geometry.size.height, alignment: .center)
VStack(alignment: .trailing)
Text(salery.hjDateString)
Text(salery.acDateString)
.frame(width: geometry.size.width / 3 * 2, height: geometry.size.height, alignment: .trailing)
.offset(CGSize(width: -45, height: 0))
)
.frame(width: .none, height: 90, alignment: .center)
.background(Color("listItemBGColor"))
.cornerRadius(8)
struct SaleryCellItem2 : View
var salery: FutureSalery
var body: some View
VStack
Text("\(salery.remainingDays)")
VStack(alignment: .trailing)
Text(salery.hjDateString)
Text(salery.acDateString)
extension CalendarView
func addFutureSalery()
// get the last salery in list
var lastDate = Date()
if (saleries.count > 0)
lastDate = saleries.last!.dateObject
var dayOfSalery = 1
switch settings.organizationType
case SaleryOrgType.gov.rawValue:
dayOfSalery = 27
case SaleryOrgType.privateSector.rawValue:
dayOfSalery = Int(UserDefaults.standard.double(forKey: "saleryDayIfPrivateSector"))
case SaleryOrgType.taqaod.rawValue:
dayOfSalery = 20
default:
dayOfSalery = 1
// if list is empty -> get the soonest salery from today date
// get the next salery after that salery
// append
var nearestDate = Date()
if (saleries.count > 0)
nearestDate = lastDate.nextMonthDate(withDayNumber: dayOfSalery)
else
// first item
nearestDate = lastDate.nearestDate(withNumber: dayOfSalery)
self.saleries.append(FutureSalery(dateObject: nearestDate))
print("count \(self.saleries.count)")
func removeFutureSalery()
if(self.saleries.count > 0)
self.saleries.removeLast()
print("count \(self.saleries.count)")
struct DateItem: Identifiable
var id = UUID()
var title:String
struct CalendarView_Previews: PreviewProvider
static var previews: some View
Group
CalendarView()
.previewDevice(PreviewDevice(rawValue: "iPhone 11 Pro Max"))
.previewDisplayName("iPhone 11 Pro Max")
【问题讨论】:
你能显示更多代码吗?如果我将上面的代码嵌入到 List 中,我看不到任何问题。 ScrollView 没有自己的内部几何图形,因此无论是间隔还是几何阅读器都不应该在顶层。这可能是崩溃的原因(渲染引擎而不是循环寻找布局的锚点)。 【参考方案1】:感谢@Asperi 在 cmets 中提供解决方案。
问题在于几何阅读器。
GeometryReader 不应该在 ScrollView 中,因为它会导致内存泄漏。
所以,只要我们有这样的代码
ScrollView
VStack
GeometryReader(content: geometry in // <- look at this
...
应该改成这个
GeometryReader(content: geometry in // <- look at this
ScrollView
VStack
...
谢谢
【讨论】:
以上是关于在 SwiftUI 中滚动时,许多项目列表崩溃,我该如何解决?的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI - 防止列表在项目选择时将滚动位置重置为顶部