The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions IOS Swift

Viewed 44

Hi the stackOverFlow Swift community, I am making a multiple image picker following the tutorial in this video: https://www.youtube.com/watch?v=SfcJewIgF7Q. However, on my struct CustomPicker View, I always getting this bug "The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions". I tried troubleshoot by removing the line one by one and I noticed if I remove

ForEach(i..<i+3, id: \.self){j in

                                    HStack{
                                        if j < self.data.count{
                                            Card(data: self.data[j], selected: self.$selected)
                                        }
                                    }
                            }

Then the error will be gone, the full code is shown below

import SwiftUI
import Photos

struct Home: View{
    @State var selected : [UIImage] = []
    @State var show = false
    var body: some View{
        ZStack{
            Color.black.opacity(0.07).edgesIgnoringSafeArea(.all)
            VStack{
                if !self.selected.isEmpty{
                    ScrollView(.horizontal, showsIndicators: false){
                        HStack(spacing: 20){
                            ForEach(self.selected, id: \.self){i in
                                Image(uiImage: i)
                                    .resizable()
                                    .frame(width: UIScreen.main.bounds.width - 40, height: 250)
                                    .cornerRadius(15)
                            }
                        }
                        .padding(.horizontal, 20)
                    }
                }
            }
            
            Button(action: {
                self.selected.removeAll()
                self.show.toggle()
            }){
                Text("Image Picker")
                    .foregroundColor(.white)
                    .padding(.vertical, 10)
                    .frame(width: UIScreen.main.bounds.width/2)
            }.background(Color.red).clipShape(Capsule()).padding(.top, 25)
        }
        if self.show {
            CustomPicker(selected: self.$selected, show: self.$show)
        }
    }
}

struct CustomPicker: View {
    @Binding var selected:[UIImage]
    @State var data: [Images] = []
    @State var grid: [Int] = []
    @Binding var show : Bool
    @State var disabled = false
    
    var body: some View {
        GeometryReader{_ in
            VStack{
                if !self.grid.isEmpty{
                    HStack{
                        Text("Pick a Image").fontWeight(.bold)
                        Spacer()
                    }
                    .padding(.leading)
                    .padding(.top)
                    
                    ScrollView(.vertical, showsIndicators: false){
                        VStack(spacing: 20){
                            ForEach(self.grid, id: \.self){ i in
                                HStack(spacing:8){
                                    ForEach(i..<i+3, id: \.self){j in
                                        HStack{
                                            if j < self.data.count{
                                                Card(data: self.data[j], selected: self.$selected)
                                            }
                                        }
                                    }
                                    if self.data.count % 3 != 0 && i == self.grid.last!{
                                        Spacer()
                                    }
                                }
                                .padding(.leading, (self.data.count % 3 != 0 && i == self.grid.last!) ? 15:0)
                            }
                        }
                    }
                    Button(action:{
                        self.show.toggle()
                    }){
                        Text("Select")
                            .foregroundColor(.white)
                            .padding(.vertical, 10)
                            .frame(width: UIScreen.main.bounds.width/2)
                    }
                    .background(Color.red.opacity((self.selected.count != 0) ? 1 : 0.5))
                    .clipShape(Capsule())
                    .padding(.bottom, 25)
                    .disabled((self.selected.count != 0) ? false : true)
                }
                else {
                    if self.disabled{
                        Text("Please enable storage access")
                    }else{
                        Indicator()
                    }
                }
            }
            .frame(width: UIScreen.main.bounds.width - 40, height: UIScreen.main.bounds.height / 1.5)
            .background(Color.white)
            .cornerRadius(12)
        }
        .background(Color.black.opacity(0.1).edgesIgnoringSafeArea(.all)
                        .onTapGesture {
            self.show.toggle()
        })
        .onAppear{
            PHPhotoLibrary.requestAuthorization{(status) in
                if status == .authorized{
                    self.getAllImages()
                    self.disabled = false
                }
                else {
                    print("not authorized")
                    self.disabled = true
                }
            }
        }
    }
    
    func getAllImages(){
        let req = PHAsset.fetchAssets(with: .image, options: .none)
        DispatchQueue.global(qos: .background).async {
            req.enumerateObjects {(asset, _, _) in
                let options = PHImageRequestOptions()
                options.isSynchronous = true
                
                PHCachingImageManager.default().requestImage(for: asset, targetSize: .init(), contentMode: .default, options: options){(image, _) in
                    let data1 = Images(image: image!, selected: false)
                    self.data.append(data1)
                }
            }
            if req.count == self.data.count{
                self.getGrid()
            }
        }
    }
    
    func getGrid(){
        for i in stride(from: 0, to: self.data.count, by: 3){
            self.grid.append(i)
        }
    }
}

struct Images {
    var image : UIImage
    var selected : Bool
}

struct Card : View {
    @State var data : Images
    @Binding var selected: [UIImage]
    var body : some View {
        ZStack{
            Image(uiImage: self.data.image).resizable()
            
            if self.data.selected{
                ZStack{
                    Color.black.opacity(0.5)
                    Image(systemName: "checkmark")
                        .resizable()
                        .frame(width: 30, height: 30)
                        .foregroundColor(.white)
                }
            }
        }.frame(width: (UIScreen.main.bounds.width - 80)/3, height: 90)
            .onTapGesture {
                if !self.data.selected {
                    self.data.selected = true
                    self.selected.append(self.data.image)
                }
                else {
                    for i in 0..<self.selected.count{
                        if self.selected[i] == self.data.image{
                            self.selected.remove(at: i)
                            self.data.selected = false
                            return
                        }
                    }
                }
            }
    }
}


struct Indicator : UIViewRepresentable {
    func makeUIView(context: Context) -> UIActivityIndicatorView {
        let view = UIActivityIndicatorView(style: .large)
        view.startAnimating()
        return view
    }
    
    func updateUIView(_ uiView: UIActivityIndicatorView, context: Context) {
    }
}

I have totally no idea why the error can be solved by removing these lines. May I ask why this error occur and how I can prevent it? Thanks

0 Answers
Related