Search code examples
swiftuitableviewcore-bluetooth

(Automatic) reloadData on Tableview(tabbar2) once Array is updated in tabbar1 (without needing to change tabbars)


tabbar1 - I'm using core-bluetooth to connect to some peripherals. Once it connects, I update an array.

 func populateFoundBTArray(peripheral: CBPeripheral, service:CBService) {
     discoveredBTDevices.append(BTPeripheral.init(
                               id: discoveredBTDevices.count, 
                               name: peripheral.name!, 
                               uuid: peripheral.identifier, 
                               desc: service.uuid.description
                               connected: peripheral.state == .connected ? true : false ))
    }

in TabBar2 - I have some prototype (custom) cells hooked up via a XIB file via a combo of Static Cells and dynamic cells (similar to this solution - https://stackoverflow.com/a/49157374/14414215)

within TabBar2 - I have the tableView.reloadData() call which is great whereby, whenever I switch to this tabbar2, the tableview will get updated. (but I have to physically go to tabbar1 --> tabbar2 to trigger this update)

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(true)
    tableView.reloadData()
  }

my goal Is would like to be able to get the tableview to reload whenever the array discoveredBTDevices gets updated.

I did try

let pop = tabbar2()
pop.tableView.reloadData() // also tried reloadSections(1 but didn't work

along with some more answers I found on SO but none of them worked. (I did not try any segues / notifications as currently I just have the discoveredBTDevices as a global variable to simplify my initial test)


Solution

  • I am posting my own answer as to how I solved this issue of mine. It is not a full solution but rather a workaround but I believe that it is suitable.

    From the original post, the goal is to get the tableviewcell to refresh once the array discoveredBTDevices gets updated. To Recap, currently the table will only refresh once the user switch to tabbar1 and then back to tabbar2 (due to the reloadData() called in viewDidAppear)

    After searching and reading through 40+ SO pages on UITableview and not finding an answer, I decided to utilise a UIButton to do manual table reload.

      // https://stackoverflow.com/a/53032365/14414215
      //
      // https://stackoverflow.com/a/44735567/14414215
      //
      override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    
        if section == deviceSection { // this is my paired device section of the static table
          let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 30.0))
          
          let sectionHeader = UILabel(frame: CGRect(x: 8, y: 0, width: 200, height: 30.0))
          sectionHeader.text = "PAIRED BLUETOOTH DEVICES"
          sectionHeader.font = UIFont.systemFont(ofSize: 12)
          sectionHeader.textColor = UIColor.systemGray
          
          let reloadButton = UIButton(frame: CGRect(x: tableView.frame.width-150, y: 0, width: 150, height: 30.0))
          reloadButton.setTitle("Reload", for: .normal)
          reloadButton.addTarget(self, action: #selector(ReloadButtonTapped), for: .touchUpInside)
          reloadButton.semanticContentAttribute = UIApplication.shared
              .userInterfaceLayoutDirection == .rightToLeft ? .forceLeftToRight : .forceRightToLeft
    
          headerView.addSubview(reloadButton)
          headerView.addSubview(sectionHeader)
          return headerView
        }
        return super.tableView(tableView, viewForHeaderInSection: section)
      }
    
    
      @objc func ReloadButtonTapped(_ sender : Any) {
        tableView.reloadData()
      }
    

    I have linked 2 SO pages which shows the implementation and merged it slightly as using viewForHeaderInSection will remove all stylings from using Apple's native header hence the addition of the sectionHeader