Reputation: 769
I have an array in swift which is constantly being updated by another method and it also needs to be loaded to table view after update. The method updating the array is called frequently. I am having threading issue. I tried using a lock on array when the updating method is called. It did improve but but it is not working quite well as well. I am getting fatal error: Index out of range
when it is updating the table in case of large number of elements (around >50) in array.
What would be the best approach to handle this situation and make it thread-safe. I am new to Swift.
Below is the function to update myArray:
func updateMyArray() {
objc_sync_enter(self.myArray)
//do some stuff with my Array
//…………add some elements in array………
//…………remove some elements in array……
DispatchQueue.main.async {
self.myTable.reloadData()
}
objc_sync_exit(self.myArray)
}
Below is the table delegate methods:
func numberOfRows(in tableView: NSTableView) -> Int {
return myArray.count
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
var cellText: String = myArray[row]
if let cell = myTable.make(withIdentifier: “myCellIdentifier", owner: nil) as? NSTableCellView {
cell.textField?.stringValue = cellText
return cell
}
}
updateMyArray() is called every 10 seconds
override func viewDidAppear() {
_ = Timer.scheduledTimer(timeInterval: 10.0, target: self, selector: #selector(self.updateMyArray), userInfo: nil, repeats: true)
}
updateMyArray() is called by pushing refresh button
@IBAction func refreshMyArray(_ sender:NSButton){
self.updateMyArray()
}
Upvotes: 0
Views: 273
Reputation: 769
This is what worked for me:
In updateMyArray() method:
func updateMyArray() {
self.updatingTableData = true
//do some stuff with my Array
//…………add some elements in array………
//…………remove some elements in array……
self.updatingTableData = false
//following can also be done in didSet part of myArray variable
DispatchQueue.main.async {
self.myTable.reloadData()
}
}
In table view delegate method:
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
if self.updatingTableData == true || row >= self.printers.count {
return nil
}
var cellText: String = myArray[row]
if let cell = myTable.make(withIdentifier: “myCellIdentifier", owner: nil) as? NSTableCellView {
cell.textField?.stringValue = cellText
return cell
}
}
Upvotes: 0
Reputation: 420
When declaring your array add this:
var myArray=[type]() {
didSet{
DispatchQueue.main.async {
self.myTable.reloadData()
}
}
}
So whenever your array is updated the tableView is reloaded with proper data.
Upvotes: 1