Home > Software engineering >  (swift) Why the fetching CoreData function executes before the saving to CoreData function?
(swift) Why the fetching CoreData function executes before the saving to CoreData function?

Time:01-04

I am retrieving some data and save it to CoreData entity. Then I try to fetch it and populate a UITableView on the viewController module. There are 3 major functions in viewController, clearCoreData, processCirclCVEs and retrieveCVEDaily. clearCoreData deletes all data from the CoreData entity to prepare for a new set of data. processCirclCVEs retrieves and saves to CoreData. retrieveCVEDaily fetches all CoreData and reloads the UITableView. In Debugging mode, I noticed that the very first object being accessed is var oCVEDaily: [NSManagedObject] = [], an object at the top of the class, used for the TableView loading. As a result, it is still empty and it assigns 0 rows to the TableView

func tableView(_ tvwCVEDaily: UITableView, numberOfRowsInSection section: Int) -> Int {
        return oCVEDaily.count
    }

Then the flow goes into the retrieveCVEDaily function before executing the other 2 functions (clearCoreData, processCirclCVEs). Finally, the data is actually retrieved and saved (in CoreData entity) but never loaded in the TableView. Below are sections of my app

override func viewDidLoad() {
        super.viewDidLoad()
        initImages()
        tvwCVEDaily.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
        
        clearCoreData()
        processCirclCVEs()
        retrieveCVEDaily()
    }

func processCirclCVEs()
    {
        //CRUD
        let cdCRUD = CRUD()
        
        let oCirclCVEs = CirclCVEs()
        Task
        {
            await oCirclCVEs.jsonDataRequest()
            
            // DEBUG
            self.txtvJSON.text = self.txtvJSON.text   "CirclCVEs\n"
            txtvJSON.text = "Array elements: "   String((oCirclCVEs.arrCVE?.results.count)!)
            
            var strID : String
            var strSeverity : String
            var strCVSS : String? = nil
            var strModified : String
            var strSummary : String
            var strCVEs : String = ""

            for eachCVE in oCirclCVEs.arrCVE!.results
            {
                // get each the CVE info
                strID = eachCVE.id
                if (eachCVE.cvss != nil)
                {
                    strCVSS = String(eachCVE.cvss!)
                }
                else
                {
                    strCVSS = ""
                }
                strModified = eachCVE.Modified
                strSummary = eachCVE.summary

                strCVEs = strCVEs   strID   " - "   strCVSS!   "\n"
                
                //Insert into CoreData
                cdCRUD.cdCreate(pcveNumber: strID, pcveCVSS: 0.0, pcveDate: strModified, pcveDescription: strSummary)
                // DEBUG
                print("Created")
            }

            self.txtvJSON.text = self.txtvJSON.text   strCVEs
        }
        retrieveCVEDaily()
    }

func retrieveCVEDaily()
    {
        //CRUD
        let ocdCRUD = CRUD()
        var strCVEs : String = ""
        var strCVENumber : String = ""
        var strCVECVSS : Float = 0.0
        var strCVEDate : String = ""
        
        ocdCRUD.cdRetrieve()
        oCVEDaily =  ocdCRUD.nsmoCVEDaily! as! [NSManagedObject]
        for data in oCVEDaily
        {
            strCVENumber = data.value(forKey: "cveNumber") as! String
            if (data.value(forKey: "cveCVSS")  != nil)
            {
                strCVECVSS = data.value(forKey: "cveCVSS") as! Float
            }
            else
            {
                strCVECVSS = 0.0
            }
            strCVEDate = data.value(forKey: "cveDate") as! String
            strCVEs = strCVEs   strCVENumber   " - "   String(strCVECVSS)   " - "   strCVEDate   "\n"
        }
        
        self.txtvJSON.text = self.txtvJSON.text   strCVEs
        self.tvwCVEDaily.reloadData()
    }


// MARK: - UITableViewDataSource
extension ViewController: UITableViewDataSource {
    func tableView(_ tvwCVEDaily: UITableView, numberOfRowsInSection section: Int) -> Int {
        return oCVEDaily.count
    }

    func tableView(_ tvwCVEDaily: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let oCVE = oCVEDaily[indexPath.row]
        let cell = tvwCVEDaily.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.text = oCVE.value(forKeyPath: "cveNumber") as? String
        return cell
    }
}

Can someone please let me know what I am doing wrong?

CodePudding user response:

The reason retrieveCVEDaily() is executing before processCirclCVEs() is because processCirclCVEs() kicks off a Task, which is an asynchronous thread . When a Task is created, the code block within the Task is passed off to another thread to execute, and then the current thread continues executing the code after the Task block. Because the Task includes await code, it will take longer to execute, than the rest of the code on the current thread.

Thread 1: ViewDidLoad -> clearCoreData -> create Task -> retreiveCVEDaily
Thread 2:                                      |-> schedule Task -> processCirclCVE 

I also noticed that you are calling retrieveCVEDaily() twice, once in ViewDidLoad(), and another time within the processCirclCVE(). Not sure if that is intended, but seems like wasted computation.

To fix this, I suggest removing the retrieveCVEDaily() call from ViewDidLoad(), and then moving the retrieveCVEDaily() call in the processCirclCVE() function into the Task block so that it is executed sequentially.

override func viewDidLoad() {
    super.viewDidLoad()
    initImages()
    tvwCVEDaily.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
    
    clearCoreData()
    processCirclCVEs()
}

func processCirclCVEs()
{
    //CRUD
    let cdCRUD = CRUD()
    
    let oCirclCVEs = CirclCVEs()
    Task
    {
        await oCirclCVEs.jsonDataRequest()
        
        // DEBUG
        self.txtvJSON.text = self.txtvJSON.text   "CirclCVEs\n"
        txtvJSON.text = "Array elements: "   String((oCirclCVEs.arrCVE?.results.count)!)
        
        var strID : String
        var strSeverity : String
        var strCVSS : String? = nil
        var strModified : String
        var strSummary : String
        var strCVEs : String = ""

        for eachCVE in oCirclCVEs.arrCVE!.results
        {
            // get each the CVE info
            strID = eachCVE.id
            if (eachCVE.cvss != nil)
            {
                strCVSS = String(eachCVE.cvss!)
            }
            else
            {
                strCVSS = ""
            }
            strModified = eachCVE.Modified
            strSummary = eachCVE.summary

            strCVEs = strCVEs   strID   " - "   strCVSS!   "\n"
            
            //Insert into CoreData
            cdCRUD.cdCreate(pcveNumber: strID, pcveCVSS: 0.0, pcveDate: strModified, pcveDescription: strSummary)
            // DEBUG
            print("Created")
        }

        self.txtvJSON.text = self.txtvJSON.text   strCVEs
        retrieveCVEDaily()
    }
    
}

[...]
  • Related