需要实时更新 UITableViewCell 数据

Need to update UITableViewCell data real time

提问人:Madushan Senavirathna 提问时间:9/22/2023 最后编辑:Madushan Senavirathna 更新时间:9/22/2023 访问量:39

问:

我正在开发蓝牙应用程序,从广播设备获取设备数据,所有数据都没有任何问题,我们用这个代码来测试我们的设备,这个代码库只过滤那些设备

let deviceLocations: [字符串: 字符串] = [ “00000534”: “办公室”, “00000523”: “接待处”, “00000525”: “午餐室” ]

我为此目的添加了 所有人都在解决任何问题

我有表格视图,它显示设备名称、UUID、RSSI 和位置

我的问题是我从设备获取实时值,但这些值没有在表视图单元格中更新。

需要实时更新表视图数据

值得一提的是,我添加了 5 秒钟的复习,但仍然不起作用

我已经把我的代码打碎了。有人请帮我解决这个问题

import UIKit
import CoreBluetooth
import Combine

class DeviceListViewController: UIViewController, BluetoothManagerDelegate, UITableViewDelegate, UITableViewDataSource, CBCentralManagerDelegate {

    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var strongestRSSILabel: UILabel!
    
    var bluetoothManager: BluetoothManager!
    var centralManager: CBCentralManager!
    var discoveredDevices: [CBPeripheral] = []
    var rssiValues: [CBPeripheral: NSNumber] = [:]
    var rssiValue: Int = 0
    var rssiUpdateTimer: Timer?
    var deviceInfoArray: [DeviceInfo] = []
    
    @Published var strongestRSSI: NSNumber?
    var strongestPeripheral: CBPeripheral?
    
    let deviceLocations: [String: String] = [
        "00000534": "Office room",
        "00000523": "Reception",
        "00000525": "Lunch room"
    ]
    
    private var observation: AnyCancellable?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.delegate = self
        tableView.dataSource = self
        
        centralManager = CBCentralManager(delegate: self, queue: nil)
        
        bluetoothManager = BluetoothManager()
        bluetoothManager.delegate = self
        bluetoothManager.startScanning()
        
        observation = $strongestRSSI
            .sink { [weak self] newValue in
                self?.tableView.reloadData()
            }
        
        refreshTableView()
        
        rssiUpdateTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(refreshTableView), userInfo: nil, repeats: true)
        RunLoop.current.add(rssiUpdateTimer!, forMode: .common)
    }
    
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if central.state == .poweredOn {
            // Start scanning for peripheral devices with RSSI values
            central.scanForPeripherals(withServices: nil, options: nil)
        }
    }

    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        // Update the RSSI value whenever a peripheral is discovered
        rssiValue = RSSI.intValue
        
        // You may want to update your data source here as well
    }
    
    @objc func refreshTableView() {
        DispatchQueue.main.async {
            self.filterDiscoveredDevices()
            self.filterDiscoveredDevicesRSSI()
            
            // Check if strongestRSSI has changed and the strongestPeripheral is available
            if let strongestRSSI = self.strongestRSSI,
               let strongestPeripheral = self.strongestPeripheral,
               let indexPath = self.indexPathForPeripheral(strongestPeripheral) {
                let cell = self.tableView.cellForRow(at: indexPath) as? DeviceTableViewCell
                cell?.rssiLabel?.text = "RSSI: \(strongestRSSI)"
            }
            
            self.tableView.reloadData()
            print("Table view refreshed ======================================== HHHH")
        }
    }
    
    // Function to find the IndexPath for a given peripheral
    private func indexPathForPeripheral(_ peripheral: CBPeripheral) -> IndexPath? {
        for (index, device) in discoveredDevices.enumerated() {
            if device === peripheral {
                return IndexPath(row: index, section: 0)
            }
        }
        return nil
    }
    
    func filterDiscoveredDevices() {
        discoveredDevices = discoveredDevices.filter { peripheral in
            if let name = peripheral.name {
                return ["00000534", "00000523", "00000525"].contains(name)
            }
            return false
        }
    }
    
    func filterDiscoveredDevicesRSSI() {
        // Filter the discovered devices based on the names
        let filteredDevices = discoveredDevices.filter { peripheral in
            if let name = peripheral.name {
                return ["00000534", "00000523", "00000525"].contains(name)
            }
            return false
        }
        
        // Fetch RSSI values for the filtered devices
        for peripheral in filteredDevices {
            peripheral.readRSSI()
        }
        
        // Determine the strongest RSSI value among the filtered devices
        var strongestRSSI: NSNumber?
        var strongestLocation: String?
        
        for peripheral in filteredDevices {
            if let rssi = rssiValues[peripheral] {
                if strongestRSSI == nil || rssi.intValue > strongestRSSI!.intValue {
                    strongestRSSI = rssi
                    strongestLocation = deviceLocations[peripheral.name ?? ""]
                }
            }
        }
        
        // Update strongestRSSI using @Published
        self.strongestRSSI = strongestRSSI
        
        // Update the UILabel with the combined label
        var combinedLabelText = "Strongest RSSI: N/A"
        if let strongestRSSI = strongestRSSI, let strongestLocation = strongestLocation {
            combinedLabelText = "Strongest RSSI: \(strongestRSSI), Location: \(strongestLocation)"
        }
        
        strongestRSSILabel.text = combinedLabelText
    }
    
    // Implement BluetoothManagerDelegate methods
    func bluetoothManager(_ manager: BluetoothManager, didDiscoverPeripheral peripheral: CBPeripheral, withRSSI RSSI: NSNumber) {
        if !discoveredDevices.contains(peripheral) {
            rssiValues[peripheral] = RSSI
            discoveredDevices.append(peripheral)
            filterDiscoveredDevices()
            filterDiscoveredDevicesRSSI()
            tableView.reloadData()
            
            // Check if the RSSI is stronger than the current strongest RSSI
            if strongestRSSI == nil || RSSI.intValue > strongestRSSI!.intValue {
                strongestRSSI = RSSI
                strongestPeripheral = peripheral
            }
        }
    }

    
    func refreshRSSIValues() {
        for peripheral in discoveredDevices {
            peripheral.readRSSI()
        }
    }
    
    func bluetoothManager(_ manager: BluetoothManager, didStartAdvertisingPeripheral success: Bool) {
        if success {
            // Start advertising
        } else {
            // Handle advertising failure
        }
    }
    
    // Implement UITableViewDelegate and UITableViewDataSource methods
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return discoveredDevices.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "DeviceCell", for: indexPath) as! DeviceTableViewCell
        
        let peripheral = discoveredDevices[indexPath.row]
        cell.nameLabel?.text = "Device Name: \(peripheral.name ?? "Unnamed Device")"
        cell.uuidLabel?.text = "UUID: \(peripheral.identifier.uuidString)"
        
        // Get the RSSI value from the dictionary
        if let rssi = rssiValues[peripheral] {
            cell.rssiLabel?.text = "RSSI: \(rssi)"
        } else {
            cell.rssiLabel?.text = "RSSI: N/A"
        }
        
        if let location = deviceLocations[peripheral.name ?? "Device Name"] {
            cell.locationLabel?.text = "Location: \(location)"
        } else {
            cell.locationLabel?.text = "Location: N/A"
        }
        
        return cell
    }
}
iOS Swift SwiftUI 领域

评论

0赞 Maziar Saadatfar 9/22/2023
请在 numberOfRowsInSection 中打印“discoveredDevices”并检查它。
0赞 Jay 9/23/2023
这是相当多的代码,但我认为方法就是问题所在。假设数据存储在 Realm 中(根据标签),并且该数据作为结果加载,而结果又是 tableview 的数据源,您将向 Realm 结果添加一个观察者,当该数据发生变化(添加、修改或删除)时,观察者将接收一个事件,然后重新加载您的表视图以显示更改。例如,让控制器(MVC 模式)在数据更改时更新视图)。

答: 暂无答案