首页 > 解决方案 > 在 SwiftUI 中滚动时,许多项目列表崩溃,我该如何解决?

问题描述

我在 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")

        }

    }
}

标签: swiftuiswiftui-listswiftui-foreach

解决方案


感谢@Asperi 在评论中提供解决方案。

问题是几何阅读器。

GeometryReader 不应该在 ScrollView 中,因为它会导致内存泄漏。

所以,每当我们有这样的代码

        ScrollView {
            VStack {
                 GeometryReader(content: { geometry in   // <- look at this
                 ...

应该改成这个

    GeometryReader(content: { geometry in   // <- look at this
        ScrollView {
            VStack {
                 ...

谢谢


推荐阅读