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()
}
}
[...]