QLPreviewControllerRepresentation does not conform to protocol UIViewControllerRepresentable

36 Views Asked by At

Im' new in swift and I want to understand why I got this error from my struct. I want to offer to my customer the possibility to show the file after the download.

Here is my class witch used for :

import SwiftUI
import QuickLook
import FirebaseStorage

struct AdminUsersToPaid: View {
    @EnvironmentObject var viewModel: AuthViewModel
    @StateObject var adminUserToPaid = AdminUserToPaidModel()
    @State private var soldes: [Solde] = []
    
    @State private var isShowingToast = false
    @State private var toastMessage = ""
    @State private var fileToPreview: URL?
    
    var body: some View {
        content.onAppear{
            Task{
                await adminUserToPaid.fetchSoldeData()
                soldes = adminUserToPaid.soldeList
            }
        }.toast(isShowing: $isShowingToast, text: Text(toastMessage))
            .background(
                QLPreviewControllerRepresentation(fileURL: $fileToPreview)
            )
    }
    
    var content: some View{
        VStack{
            HStack{
                Text("Utilisateur à payer")
                    .font(.system(size: 24).bold())
                Spacer()
                Image(systemName: "eurosign")
                    .font(.system(size: 32))
                    .foregroundColor(.black)
            }.padding()
            Spacer()
            List(soldes){ solde in
                
                HStack{
                    VStack{
                        Text("Nom Complet").font(.system(size: 14)).multilineTextAlignment(.center)
                        Text("\(solde.proprietaire)").padding(.top,5).font(.system(size: 12)).foregroundColor(.gray).multilineTextAlignment(.center)
                    }
                    Spacer()
                    VStack{
                        Text("Date de la demande").font(.system(size: 14)).multilineTextAlignment(.center)
                        Text("\(formatDate(solde.date))").padding(.top,5).font(.system(size: 12)).foregroundColor(.gray).multilineTextAlignment(.center)
                    }
                    Spacer()
                    VStack{
                        Text("Etat de la demande").font(.system(size: 14)).multilineTextAlignment(.center)
                        Text("\(solde.etat)").padding(.top,5).font(.system(size: 12)).foregroundColor(.gray).multilineTextAlignment(.center)
                    }
                    Spacer()
                    VStack{
                        Text("Total du solde").font(.system(size: 14)).multilineTextAlignment(.center)
                        Text("\(solde.total)").padding(.top,5).font(.system(size: 12)).foregroundColor(.gray).multilineTextAlignment(.center)
                    }
                    Spacer()
                    Button {
                        downloadInvoice(forSolde: solde)
                            } label: {
                                Text("Voir la facture").multilineTextAlignment(.center)
                            }
                }
            }
            NavigationLink {
                AdminDashboard().navigationBarBackButtonHidden(true)
            } label: {
                HStack(spacing: 3){
                    Text("Retour à la page")
                    Text("Principale").fontWeight(.bold)
                }.font(.system(size: 14))
            }
        }
    }
}

struct QLPreviewControllerRepresentation: UIViewControllerRepresentable {
    @Binding var fileURL: URL?
    
    func makeUIViewController(context: Context) -> some QLPreviewController {
        let controller = QLPreviewController()
        controller.dataSource = context.coordinator
        return controller
    }

    func updateUIViewController(_ uiViewController: QLPreviewController, context: Context) {
        uiViewController.reloadData()
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, QLPreviewControllerDataSource {
        let parent: QLPreviewControllerRepresentation

        init(_ parent: QLPreviewControllerRepresentation) {
            self.parent = parent
        }

        func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
            return parent.fileURL != nil ? 1 : 0
        }

        func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
            return parent.fileURL! as QLPreviewItem
        }
    }
}

extension AdminUsersToPaid {
    func downloadInvoice(forSolde solde: Solde) {
        let filename = solde.facture
        let storageRef = Storage.storage().reference().child("invoices/\(solde.proprietaire)/\(solde.id)/\(filename)")
        
        let localURL = FileManager.default.temporaryDirectory.appendingPathComponent(filename)

        storageRef.write(toFile: localURL) { url, error in
            if let error = error {
                toastMessage = "Erreur lors du téléchargement: \(error.localizedDescription)"
                isShowingToast.toggle()
            } else if let url = url {
                fileToPreview = url
            }
        }
    }
}

private func formatDate(_ date: Date) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "dd/MM/yyyy"
    return dateFormatter.string(from: date)
}

struct AdminUsersToPaid_Previews: PreviewProvider {
    static var previews: some View {
        AdminUsersToPaid()
    }
}

Thanks to all for helping. The problem occur on this line to be more explicit but don't know why...

struct QLPreviewControllerRepresentation: UIViewControllerRepresentable {

if somebody can explain me what is wrong in this part of the structure I will be thankful.

1

There are 1 best solutions below

0
Windows Frame On

import SwiftUI
import QuickLook
import FirebaseStorage

struct AdminUsersToPaid: View {
    @EnvironmentObject var viewModel: AuthViewModel
    @StateObject var adminUserToPaid = AdminUserToPaidModel()
    @State private var soldes: [Solde] = []
    
    @State private var isShowingToast = false
    @State private var toastMessage = ""
    @State private var fileToPreview: URL?
    
    var body: some View {
        content.onAppear{
            Task{
                await adminUserToPaid.fetchSoldeData()
                soldes = adminUserToPaid.soldeList
            }
        }.toast(isShowing: $isShowingToast, text: Text(toastMessage))
            .background(
                QLPreviewControllerRepresentation(fileURL: $fileToPreview)
            )
    }
    
    var content: some View{
        VStack{
            HStack{
                Text("Utilisateur à payer")
                    .font(.system(size: 24).bold())
                Spacer()
                Image(systemName: "eurosign")
                    .font(.system(size: 32))
                    .foregroundColor(.black)
            }.padding()
            Spacer()
            List(soldes){ solde in
                
                HStack{
                    VStack{
                        Text("Nom Complet").font(.system(size: 14)).multilineTextAlignment(.center)
                        Text("\(solde.proprietaire)").padding(.top,5).font(.system(size: 12)).foregroundColor(.gray).multilineTextAlignment(.center)
                    }
                    Spacer()
                    VStack{
                        Text("Date de la demande").font(.system(size: 14)).multilineTextAlignment(.center)
                        Text("\(formatDate(solde.date))").padding(.top,5).font(.system(size: 12)).foregroundColor(.gray).multilineTextAlignment(.center)
                    }
                    Spacer()
                    VStack{
                        Text("Etat de la demande").font(.system(size: 14)).multilineTextAlignment(.center)
                        Text("\(solde.etat)").padding(.top,5).font(.system(size: 12)).foregroundColor(.gray).multilineTextAlignment(.center)
                    }
                    Spacer()
                    VStack{
                        Text("Total du solde").font(.system(size: 14)).multilineTextAlignment(.center)
                        Text("\(solde.total)").padding(.top,5).font(.system(size: 12)).foregroundColor(.gray).multilineTextAlignment(.center)
                    }
                    Spacer()
                    Button {
                        downloadInvoice(forSolde: solde)
                            } label: {
                                Text("Voir la facture").multilineTextAlignment(.center)
                            }
                }
            }
            NavigationLink {
                AdminDashboard().navigationBarBackButtonHidden(true)
            } label: {
                HStack(spacing: 3){
                    Text("Retour à la page")
                    Text("Principale").fontWeight(.bold)
                }.font(.system(size: 14))
            }
        }
    }
}

struct QLPreviewControllerRepresentation: UIViewControllerRepresentable {
    typealias UIViewControllerType = QLPreviewController
    @Binding var fileURL: URL?
    
    func makeUIViewController(context: Context) -> QLPreviewController {
        let controller = QLPreviewController()
        controller.dataSource = context.coordinator
        return controller
    }
    
    func updateUIViewController(_ uiViewController: QLPreviewController, context: Context) {
        uiViewController.reloadData()
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, QLPreviewControllerDataSource{
        let parent: QLPreviewControllerRepresentation
        
        init(_ parent: QLPreviewControllerRepresentation) {
            self.parent = parent
        }
        
        func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
            return parent.fileURL != nil ? 1 : 0
        }
        
        func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
            guard let url = parent.fileURL else{
                fatalError("L'url devrait être à jour")
            }
            return url as QLPreviewItem
        }
    }
}


extension AdminUsersToPaid {
    func downloadInvoice(forSolde solde: Solde) {
        let filename = solde.facture
        let storageRef = Storage.storage().reference().child("invoices/\(solde.proprietaire)/\(solde.id)/\(filename)")
        
        let localURL = FileManager.default.temporaryDirectory.appendingPathComponent(filename)

        storageRef.write(toFile: localURL) { url, error in
            if let error = error {
                toastMessage = "Erreur lors du téléchargement: \(error.localizedDescription)"
                isShowingToast.toggle()
            } else if let url = url {
                fileToPreview = url
            }
        }
    }
}

private func formatDate(_ date: Date) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "dd/MM/yyyy"
    return dateFormatter.string(from: date)
}

struct AdminUsersToPaid_Previews: PreviewProvider {
    static var previews: some View {
        AdminUsersToPaid()
    }
}