ios – SwiftUI CoreData Importing CSV file


i am trying to establish CSV importing to my project. so that when pressing on Import CSV button, it will give user option to choose file and processed to importing and save it to CoreData entity. But the problem is that, after choosing the file, it will give me the selected file name and File Read Successfull, and i am getting error (( Error the operation could not be completed. (Foundation._GenericObjCError error 0.) )). can please someone help me. i would appreciate it.

import SwiftUI
import CoreData
import UniformTypeIdentifiers


struct CSVImportView: View {
    
    @State private var document: MessageDocument = MessageDocument(message: "Hello, World!")
    @State private var fileContent: String = ""
    @State private var errorMessage: String = ""
    @State private var showAlert: Bool = false
    
    @Environment(\.managedObjectContext) private var moc
    @State private var isImporting: Bool = false
    @State private var file: URL?
    
    var body: some View {
        NavigationView {
            VStack {
                Button("Import CSV") {
                    isImporting.toggle()
                }
                
                if let file = file {
                    Text("Selected File: \(file.lastPathComponent)")
                    
                    Text(fileContent.isEmpty ? "Cannot read file" : "File Read Successfully")
                        .foregroundColor(fileContent.isEmpty ? .red : .green)
                    
                    // Remove Import Button
                    
                    GroupBox(label: Text("Message:")) {
                        TextEditor(text: $document.message)
                    }
                }
            }
            .padding()
            .navigationTitle("CSV Import")
        }
        .fileImporter(
                    isPresented: $isImporting,
                    allowedContentTypes: [.plainText],
                    allowsMultipleSelection: false
                ) { result in
                    do {
                        guard let selectedFile = try result.get().first else { return }
                        print("Selected File URL:", selectedFile) // Print the selected file URL
                        guard selectedFile.startAccessingSecurityScopedResource() else {
                            showAlertWithError(message: "Unable to access the selected file.")
                            return
                        }
                        defer { selectedFile.stopAccessingSecurityScopedResource() }

                        self.file = selectedFile

                        let fileContentData: Data
                        do {
                            fileContentData = try Data(contentsOf: selectedFile)
                        } catch let error {
                            showAlertWithError(message: "Error reading file content: \(error.localizedDescription)")
                            return
                        }
                        print("File Content:", fileContentData) // Print the file content after reading

                        guard let message = String(data: fileContentData, encoding: .utf8) else {
                            showAlertWithError(message: "Unable to read file content.")
                            return
                        }
                        document.message = message
                        fileContent = message

                        let parsedData = parseCSV(content: message)
                                        let container = NoteCoreData.shared.persistentContainer

                                        saveToCoreData(parsedData: parsedData, with: container) { success, message in
                                            if success {
                                                showAlert = true
                                                errorMessage = message // Update message to indicate success
                                            } else {
                                                showAlert = true
                                                errorMessage = message // Display error message
                                                print("Error saving data:", message)
                                            }
                                        }
                                        print("Parsed Data:", parsedData)
                       // importCSV(url: selectedFile)

                    } catch let fileError as NSError {
                        print("File error:", fileError.localizedDescription)
                        showAlertWithError(message: "File Error: \(fileError.localizedDescription)")
                    } catch {
                        showAlertWithError(message: error.localizedDescription)
                    }
                }
                .alert(isPresented: $showAlert) {
                    Alert(title: Text("Error"), message: Text(errorMessage), dismissButton: .default(Text("OK")))
                }
            }
    
    func importCSV(url: URL) {
        do {
            let content = try String(contentsOf: url, encoding: .utf8)
            let parsedData = parseCSV(content: content)
            let container = NoteCoreData.shared.persistentContainer

            saveToCoreData(parsedData: parsedData, with: container) { success, message in
                if success {
                    showAlert = true
                    errorMessage = message // Update message to indicate success
                } else {
                    showAlert = true
                    errorMessage = message // Display error message
                    print("Error saving data:", message)
                }
            }
        } catch {
            showAlertWithError(message: error.localizedDescription)
        }
    }
    
    func parseCSV(content: String) -> [Note] {
            var parsedData: [Note] = []
            let rows = content.components(separatedBy: "\n")

            let possibleDateFormats = ["MM/dd/yyyy", "dd/MM/yyyy", "yyyy-MM-dd"]

            for row in rows {
                let columns = row.components(separatedBy: ",")

                if columns.count >= 3 {
                    let title = columns[0]
                    let dateString = columns[1]
                    let noteContent = columns[2]

                    if let date = tryFixingDate(dateString, possibleDateFormats: possibleDateFormats) {
                        let note = Note()
                        note.title = title
                        note.date = date
                        note.noteContent = noteContent
                        parsedData.append(note)
                    } else {
                        print("Unable to convert date:", dateString)
                    }
                } else if !row.isEmpty {
                    print("Incomplete row:", row)
                }
            }

            return parsedData
        }
  
    func saveToCoreData(parsedData: [Note], with container: NSPersistentContainer, completion: @escaping (Bool, String) -> Void) {
           let context = container.viewContext

           for note in parsedData {
               let newNote = Note(context: context)
               newNote.userID = "UniqueUserID"
               newNote.id = UUID()
               newNote.title = note.title
               newNote.date = note.date
               newNote.noteContent = note.noteContent
               newNote.dataType = "Note"
           }

           do {
               try context.save()
               completion(true, "Data saved successfully!") // Data saved successfully
           } catch {
               completion(false, error.localizedDescription) // Error occurred during saving
           }
       }

    func tryFixingDate(_ dateString: String, possibleDateFormats: [String]) -> Date? {
        let dateFormatter = DateFormatter()
        for format in possibleDateFormats {
            dateFormatter.dateFormat = format
            if let parsedDate = dateFormatter.date(from: dateString) {
                return parsedDate
            }
        }
        return nil
    }

    
    // Function to show alert with error message
      func showAlertWithError(message: String) {
          errorMessage = message
          showAlert = true
          print("Error:", message)
      }

}
struct MessageDocument: FileDocument {
    static var readableContentTypes: [UTType] { [.plainText] }
    var message: String

    init(message: String) {
        self.message = message
    }

    init(configuration: ReadConfiguration) throws {
        guard let data = configuration.file.regularFileContents,
              let string = String(data: data, encoding: .utf8)
        else {
            throw CocoaError(.fileReadCorruptFile)
        }
        message = string
    }

    func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
        return FileWrapper(regularFileWithContents: message.data(using: .utf8)!)
    }

}

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img