HomeiOS Developmentios - the best way to migrate parsed JSON save to CoreData...

ios – the best way to migrate parsed JSON save to CoreData to SwiftData


i am new on swift language , i hava an app with code to parse and decode json then reserve it to core information and a few core information func the fetch particular information , i dont know the best way to change it to swiftdata
anybody have thought ?
particularly the parseAndStoreQuizJSONData func and the delete func
the best way to take care of that please ?

class QuizDataViewModel: ObservableObject {
   
    
    
    
//    MARK: Quiz for Board funcs
    @Printed var selectedBoardQuizQuestions : [QuizQuestion] = []
    @Printed var selectedQuizSystem: QuizSystem?
    
    func numberOfQuestionsForBoardFor(month: Int, half: Int, 12 months: Int) -> Int {
        guard let quizQuestions = selectedQuizSystem?.quizQuestions?.allObjects as? [QuizQuestion] else { return 0 }
        return quizQuestions.filter {
            let (questionPart, questionMonth, questionYear, _) = extractDataFromId(id: Int($0.id))
            return questionYear == 12 months && questionPart == half && questionMonth == month
        }.rely
    }
  

    func selectQuestionsForBoardQuiz(_ numberOfQuestions: Int, for month: Int, half: Int, 12 months: Int) {
        guard let quizQuestions = selectedQuizSystem?.quizQuestions?.allObjects as? [QuizQuestion] else { return }
        
        let relevantQuestions = quizQuestions.filter {
            let (questionPart, questionMonth, questionYear, _) = extractDataFromId(id: Int($0.id))
            return questionYear == 12 months && questionPart == half && questionMonth == month
        }
        
        if numberOfQuestions >= relevantQuestions.rely {
            // If we're asking for all questions (or extra), kind them by id
            selectedBoardQuizQuestions = relevantQuestions.sorted(by: { $0.id < $1.id })
        } else {
            // If we're asking for a subset of questions, choose randomly
            selectedBoardQuizQuestions = Array(relevantQuestions.shuffled().prefix(numberOfQuestions))
        }
    }

    func extractDataFromId(id: Int) -> (half: Int, month: Int, 12 months: Int, questionId: Int) {
        let idString = String(id)

        let half = Int(idString.prefix(1))
        let month = Int(idString.dropFirst(1).prefix(2))
        let 12 months = Int(idString.dropFirst(3).prefix(4))
        let questionId = Int(idString.dropFirst(7))

        return (half ?? 0, month ?? 0, 12 months ?? 0, questionId ?? 0)
    }



    func uniqueYearsFromQuestions(in system: QuizSystem) -> [Int] {
        guard let quizQuestions = system.quizQuestions?.allObjects as? [QuizQuestion] else { return [] }
        let years = Set(quizQuestions.map { extractDataFromId(id: Int($0.id)).12 months })
        return Array(years).sorted(by: >) // kind in descending order
    }

    func uniquePartsForYear(12 months: Int, in system: QuizSystem) -> [Int] {
        guard let quizQuestions = system.quizQuestions?.allObjects as? [QuizQuestion] else { return [] }
        
        
        let components = Set(quizQuestions.filter {
            let extractedYear = extractDataFromId(id: Int($0.id)).12 months
            return extractedYear == 12 months
        }.map {
            let extractedPart = extractDataFromId(id: Int($0.id)).half
            return extractedPart
        })
        
        let uniqueParts = Array(components).sorted() // kind in ascending order
        
        return uniqueParts
    }

    func uniqueMonthsForPart(half: Int, 12 months: Int, in system: QuizSystem) -> [Int] {
        guard let quizQuestions = system.quizQuestions?.allObjects as? [QuizQuestion] else { return [] }
    
        let months = Set(quizQuestions.filter {
            let (questionPart, _, questionYear, _) = extractDataFromId(id: Int($0.id))
            return questionYear == 12 months && questionPart == half
        }.map {
            let extractedMonth = extractDataFromId(id: Int($0.id)).month
            return extractedMonth
        })
        let uniqueMonths = Array(months).sorted() // kind in ascending order
        return uniqueMonths
    }



    func fetchQuizSystemForId(systemID: Int64, branchID: Int64) {
        let context = container.viewContext
        let fetchRequest: NSFetchRequest<QuizSystem> = QuizSystem.fetchRequest()
        fetchRequest.predicate = NSPredicate(format: "id == %d AND quizBranch.id == %d", systemID, branchID)
        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "id", ascending: true)]
        
        do {
            let fetchedSystems = attempt context.fetch(fetchRequest)
            self.selectedQuizSystem = fetchedSystems.first // replace selectedQuizSystem
        } catch {
            print("Didn't fetch QuizSystem: (error)")
        }
    }
// ---------------------------------------------
    //    MARK: Func for saving any information to coredata

    func saveChanges() {
        let context = container.viewContext
        if context.hasChanges {
            do {
                attempt context.save()
                // Toggle the refreshFlag to power a UI replace
                self.refreshFlag.toggle()
            } catch {
                let nserror = error as NSError
                fatalError("Unresolved error (nserror), (nserror.userInfo)")
            }
        }
    }
    
    // ---------------------------------------------

    //    MARK: Func for QuizRandoms
    @Printed var quizSystems = [QuizSystem]()
    @Printed var quizQuestions: [QuizQuestion] = []
    @Printed var selectedSystemName: String?
    @Printed var currentSystemIndex = 0
    @Printed var quizTimeRemaining = 900
    
    func fetchQuizSystems(for branchID: Int64, excludingSystemIDs: [Int64] = []) {
        let context = container.viewContext
        context.carry out {
            let fetchQuizSystemRequest: NSFetchRequest<QuizSystem> = QuizSystem.fetchRequest()
            
            var predicates = [NSPredicate(format: "quizBranch.id == %d", branchID)]
            for id in excludingSystemIDs {
                let excludePredicate = NSPredicate(format: "id != %d", id)
                predicates.append(excludePredicate)
            }
            fetchQuizSystemRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicates)

            fetchQuizSystemRequest.sortDescriptors = [NSSortDescriptor(keyPath: QuizSystem.id, ascending: true)]
            
            do {
                let fetchedQuizSystems = attempt context.fetch(fetchQuizSystemRequest)
                self.quizSystems = fetchedQuizSystems
            } catch {
                print("Didn't fetch QuizSystem: (error)")
            }
        }
    }
    func fetchQuizQuestions(for systemID: Int64, and branchID: Int64) {
        let context = container.viewContext
        let fetchRequest: NSFetchRequest<QuizQuestion> = QuizQuestion.fetchRequest()
        fetchRequest.predicate = NSPredicate(format: "quizSystem.id == %d AND quizSystem.quizBranch.id == %d", systemID, branchID)
        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "id", ascending: true)]
        
        do {
            self.quizQuestions = attempt context.fetch(fetchRequest)
        } catch {
            print("Didn't fetch QuizQuestion objects: (error)")
        }
    }
    func selectRandomQuestions(_ rely: Int) {
        guard quizQuestions.rely >= rely else {
            print("Not sufficient questions to pick from.")
            return
        }
        quizQuestions.shuffle()
        quizQuestions = Array(quizQuestions.prefix(rely))
    }
// -------------------------------------------
    //    MARK: Func for Downloading and updating information from server
    @AppStorage("selectedBranchName") var selectedBranchName: String?
    let urlSession = URLSession.shared
    let container: NSPersistentContainer
    init(container: NSPersistentContainer) {
        self.container = container
        self.parseAndStoreQuizJSONData()
    }
    func fetchAndDecodeQuizJSONData(from url: URL, utilizing urlSession: URLSession = URLSession.shared, completion: @escaping (End result<QuizBranchTemp, Error>) -> Void) {
        let activity = urlSession.dataTask(with: url) { information, response, error in
            if let error = error {
                completion(.failure(error))
                print("One thing went flawed: (error)")
                return
            }
            guard let information = information else {
                completion(.failure(NSError(area: "", code: -1, userInfo: nil)))
                return
            }
            
            let decoder = JSONDecoder()
            do {
                let decodedData = attempt decoder.decode(QuizBranchTemp.self, from: information)
                completion(.success(decodedData))
            } catch {
                completion(.failure(error))
            }
        }
        activity.resume()
    }
    func parseAndStoreQuizJSONData() {
        let context = container.newBackgroundContext()
        context.carry out {
            guard let mainURL = URL(string: "https://instance.com/identify.json") else {
                print("Invalid URL")
                return
            }
            var request = URLRequest(url: mainURL)
            request.cachePolicy = .reloadIgnoringLocalAndRemoteCacheData
            
            URLSession.shared.dataTask(with: request) { (information, response, error) in
                if let error = error {
                    print("Didn't fetch foremost Quiz JSON: (error)")
                    return
                }
                
                guard let httpResponse = response as? HTTPURLResponse else {
                    print("Invalid response")
                    return
                }
                
                guard httpResponse.statusCode == 200 else {
                    print("HTTP Standing Code: (httpResponse.statusCode)")
                    return
                }
                
                guard let information = information else {
                    print("No information returned from foremost Quiz JSON")
                    return
                }
                let decoder = JSONDecoder()
                do {
                    let quizMainData = attempt decoder.decode(QuizMainData.self, from: information)
                    let quizStoredVersion = UserDefaults.commonplace.string(forKey: "quizMainDataVersion") ?? ""
                    print("Fetched quizMainDataVersion: (quizMainData.quizMainDataVersion)")
                    print("Saved quizMainDataVersion: (quizStoredVersion)")
                    
                    if quizMainData.quizMainDataVersion == quizStoredVersion {
                        print("quizMainDataVersion is similar because the quizStored model.")
                        return
                    }
                    
                    var parsedQuizBranchIDs = Set<Int64>()
                    var parsedQuizSystemIDs = Set<Int64>()
                    var parsedQuizQuestionIDs = Set<Int64>()
                    
                    let group = DispatchGroup()
                    for quizBranchInfo in quizMainData.quizMainDataContent {
                        print("Processing quizBranch: (quizBranchInfo.branchName)")
                        
                        let lastVersion = UserDefaults.commonplace.string(forKey: "(quizBranchInfo.branchName)Model") ?? ""
                        
                        // Add this department's ID to parsedBranchIDs
                        parsedQuizBranchIDs.insert(Int64(quizBranchInfo.id))
                        
                        if quizBranchInfo.model == lastVersion {
                            print("(quizBranchInfo.branchName) model is similar as the present model. Aborting...")
                            proceed
                        }
                        
                        guard let quizBranchURL = URL(string: quizBranchInfo.url) else {
                            print("Invalid URL for department: (quizBranchInfo.branchName)")
                            proceed
                        }
                        
                        group.enter()
                        self.fetchAndDecodeQuizJSONData(from: quizBranchURL, utilizing: self.urlSession) { lead to
                            defer { group.depart() }
                            swap outcome {
                            case .success(let quizBranch):
                                do {
                                    let fetchQuizBranchRequest: NSFetchRequest<QuizBranch> = QuizBranch.fetchRequest()
                                    fetchQuizBranchRequest.predicate = NSPredicate(format: "id == %d", quizBranch.id)
                                    
                                    let fetchedQuizBranches = attempt context.fetch(fetchQuizBranchRequest)
                                    let QuizBranchEntity = fetchedQuizBranches.first ?? QuizBranch(context: context)
                                    
                                    QuizBranchEntity.id = Int64(quizBranch.id)
                                    QuizBranchEntity.branchName = quizBranch.branchName
                                    
                                    for quizSystem in quizBranch.quizSystems {
                                        let fetchQuizSystemRequest: NSFetchRequest<QuizSystem> = QuizSystem.fetchRequest()
                                        fetchQuizSystemRequest.predicate = NSPredicate(format: "id == %d AND quizBranch.id == %d", quizSystem.id, quizBranch.id)
                                        
                                        let fetchedQuizSystems = attempt context.fetch(fetchQuizSystemRequest)
                                        let quizSystemEntity = fetchedQuizSystems.first ?? QuizSystem(context: context)
                                        
                                        quizSystemEntity.id = Int64(quizSystem.id)
                                        quizSystemEntity.systemName = quizSystem.systemName
                                        quizSystemEntity.systemSubheadline = quizSystem.systemSubheadline
                                        quizSystemEntity.systemImage = quizSystem.systemImage
                                        quizSystemEntity.quizBranch = QuizBranchEntity
                                        parsedQuizSystemIDs.insert(quizSystemEntity.id)
                                        
                                        for quizQuestion in quizSystem.quizQuestions {
                                            let fetchQuizQuestionRequest: NSFetchRequest<QuizQuestion> = QuizQuestion.fetchRequest()
                                            fetchQuizQuestionRequest.predicate = NSPredicate(format: "id == %d AND quizSystem.id == %d AND quizSystem.quizBranch.id == %d", quizQuestion.id, quizSystem.id, quizBranch.id)
                                            
                                            let fetchedQuizQuestions = attempt context.fetch(fetchQuizQuestionRequest)
                                            let quizQuestionEntity = fetchedQuizQuestions.first ?? QuizQuestion(context: context)
                                            
                                            quizQuestionEntity.id = Int64(quizQuestion.id)
                                            quizQuestionEntity.questionNumber = Int64(quizQuestion.questionNumber)
                                            quizQuestionEntity.questionContent = quizQuestion.questionContent
                                            quizQuestionEntity.choiceA = quizQuestion.choiceA
                                            quizQuestionEntity.choiceB = quizQuestion.choiceB
                                            quizQuestionEntity.choiceC = quizQuestion.choiceC
                                            quizQuestionEntity.choiceD = quizQuestion.choiceD
                                            quizQuestionEntity.choiceE = quizQuestion.choiceE
                                            quizQuestionEntity.correctAnswerLetter = quizQuestion.correctAnswerLetter
                                            quizQuestionEntity.clarification = quizQuestion.clarification
                                            quizQuestionEntity.isSolvedWrong = quizQuestion.isSolvedWrong
                                            quizQuestionEntity.isFlagged = quizQuestion.isFlagged
                                            quizQuestionEntity.isNeedReview = quizQuestion.isNeedReview
                                            quizQuestionEntity.quizSystem = quizSystemEntity
                                            parsedQuizQuestionIDs.insert(quizQuestionEntity.id)
                                        }
                                    }
                                    
                                    do {
                                        attempt context.save()
                                        print("Saved new model ((String(describing: quizBranchInfo.model))) of (quizBranchInfo.branchName) to Quiz CoreData")
                                    } catch {
                                        print("Failed to save lots of Quiz Core Knowledge: (error)")
                                    }
                                } catch {
                                    print("Didn't fetch and parse Quiz information: (error)")
                                }
                                
                                UserDefaults.commonplace.set(quizBranchInfo.model, forKey: "(quizBranchInfo.branchName)Model")
                                print("Set (quizBranchInfo.branchName) model to (quizBranchInfo.model)")
                                
                            case .failure(let error):
                                print("Didn't decode Quiz JSON for Quiz department (quizBranchInfo.branchName): (error)")
                            }
                        }
                    }
                    
                    group.notify(queue: .foremost) {
                        print("Parsed Quiz department IDs: (parsedQuizBranchIDs)")
                        // Now it is protected to delete
                        do {
                            self.deleteEntitiesNotInParsedIDs(context: context, entityName: "QuizBranch", parsedIDs: parsedQuizBranchIDs)
                            self.deleteEntitiesNotInParsedIDs(context: context, entityName: "QuizSystem", parsedIDs: parsedQuizSystemIDs)
                            self.deleteEntitiesNotInParsedIDs(context: context, entityName: "QuizQuestion", parsedIDs: parsedQuizQuestionIDs)
                            
                            attempt context.save()
                            
                            UserDefaults.commonplace.set(quizMainData.quizMainDataVersion, forKey: "quizMainDataVersion")
                        } catch {
                            print("Didn't decode foremost Quiz JSON: (error)")
                        }
                    }
                    
                } catch {
                    print("Didn't decode foremost Quiz JSON: (error)")
                }
                
                
            }.resume()
        }
    }
    func deleteEntitiesNotInParsedIDs(context: NSManagedObjectContext, entityName: String, parsedIDs: Set<Int64>) {
        let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: entityName)
        do {
            let fetchedEntities = attempt context.fetch(fetchRequest)
            for object in fetchedEntities {
                if let entity = object as? NSManagedObject, let entityId = entity.worth(forKey: "id") as? Int64 {
                    if !parsedIDs.incorporates(entityId) {
                        context.delete(entity)
                    }
                }
            }
        } catch {
            print("Didn't fetch (entityName)s: (error)")
        }
    }
//    ----------------------------------------------------------------
    
//    MARK: Func for Trainging heart
    @Printed var refreshFlag: Bool = false

    func fetchIsFlaggedQuestionsBySystem(for branchID: Int64) -> ([String: [QuizQuestion]], [QuizSystem]) {
        var isFlaggedQuizQuestionBySystem = [String: [QuizQuestion]]()
        var isFlaggedQuizSystemsArray = [QuizSystem]()
        
        // Fetch techniques for the chosen department
        self.fetchQuizSystems(for: branchID)
        
        for system in self.quizSystems {
            // Fetch flagged questions for the system
            let flaggedQuestions = fetchIsFlaggedQuestions(for: system.id)
            
            // Solely add the system to the dictionary if it has flagged questions
            if !flaggedQuestions.isEmpty {
                isFlaggedQuizQuestionBySystem[system.systemName!] = flaggedQuestions
                isFlaggedQuizSystemsArray.append(system)
            }
        }
        
        return (isFlaggedQuizQuestionBySystem, isFlaggedQuizSystemsArray)
    }
    func fetchIsFlaggedQuestions(for systemID: Int64) -> [QuizQuestion] {
        let context = container.viewContext
        let fetchRequest: NSFetchRequest<QuizQuestion> = QuizQuestion.fetchRequest()
        fetchRequest.predicate = NSPredicate(format: "quizSystem.id == %d AND isFlagged == %d", systemID, 1)
        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "id", ascending: true)]
        
        do {
            let flaggedQuestions = attempt context.fetch(fetchRequest)
            return flaggedQuestions
        } catch {
            print("Didn't fetch flagged QuizQuestion objects: (error)")
        }
        
        return []
    }
        func fetchIsSolvedWrongQuestionsBySystem(for branchID: Int64) -> ([String: [QuizQuestion]], [QuizSystem]) {
        var isSolvedWrongQuizQuestionBySystem = [String: [QuizQuestion]]()
        var isSolvedWrongQuizSystemsArray = [QuizSystem]()
        
        // Fetch techniques for the chosen department
        self.fetchQuizSystems(for: branchID)
        
        for system in self.quizSystems {
            // Fetch flagged questions for the system
            let isSolvedWrongQuestions = fetchIsSolvedWrongQuestions(for: system.id)
            
            // Solely add the system to the dictionary if it has flagged questions
            if !isSolvedWrongQuestions.isEmpty {
                isSolvedWrongQuizQuestionBySystem[system.systemName!] = isSolvedWrongQuestions
                isSolvedWrongQuizSystemsArray.append(system)
            }
        }
        
        return (isSolvedWrongQuizQuestionBySystem, isSolvedWrongQuizSystemsArray)
    }
    func fetchIsSolvedWrongQuestions(for systemID: Int64) -> [QuizQuestion] {
        let context = container.viewContext
        let fetchRequest: NSFetchRequest<QuizQuestion> = QuizQuestion.fetchRequest()
        fetchRequest.predicate = NSPredicate(format: "quizSystem.id == %d AND isSolvedWrong == %d", systemID, 1)
        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "id", ascending: true)]
        
        do {
            let isSolvedWrongQuestions = attempt context.fetch(fetchRequest)
            return isSolvedWrongQuestions
        } catch {
            print("Didn't fetch isSolvedWrong QuizQuestion objects: (error)")
        }
        
        return []
    }
    
    
    
    func fetchIsNeedReviewQuestionsBySystem(for branchID: Int64) -> ([String: [QuizQuestion]], [QuizSystem]) {
        var isNeedReviewQuizQuestionBySystem = [String: [QuizQuestion]]()
        var isNeedReviewQuizSystemsArray = [QuizSystem]()
        
        // Fetch techniques for the chosen department
        self.fetchQuizSystems(for: branchID)
        
        for system in self.quizSystems {
            // Fetch flagged questions for the system
            let isNeedReviewQuestions = fetchIsNeedReviewQuestions(for: system.id)
            
            // Solely add the system to the dictionary if it has flagged questions
            if !isNeedReviewQuestions.isEmpty {
                isNeedReviewQuizQuestionBySystem[system.systemName!] = isNeedReviewQuestions
                isNeedReviewQuizSystemsArray.append(system)
            }
        }
        
        return (isNeedReviewQuizQuestionBySystem, isNeedReviewQuizSystemsArray)
    }
    func fetchIsNeedReviewQuestions(for systemID: Int64) -> [QuizQuestion] {
        let context = container.viewContext
        let fetchRequest: NSFetchRequest<QuizQuestion> = QuizQuestion.fetchRequest()
        fetchRequest.predicate = NSPredicate(format: "quizSystem.id == %d AND isNeedReview == %d", systemID, 1)
        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "id", ascending: true)]
        
        do {
            let isNeedReviewQuestions = attempt context.fetch(fetchRequest)
            return isNeedReviewQuestions
        } catch {
            print("Didn't fetch isNeedReview QuizQuestion objects: (error)")
        }
        
        return []
    }
    
    
}```


i wish to save decoded json to swiftdata 

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments