简体   繁体   中英

Swift: How to handle synchronisation between table view and method updating table view

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()
}

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.

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
        }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM