Я пытаюсь найти способ сканирования устройств BLE и представить их в UITableView. Функции сканирования, подключения, чтения и записи для устройств BLE понятны и работают! Поэтому мои вопросы сосредоточены на взаимодействии между классами «ScanTableView» и «BletoothManager».Сканирование устройств BLE и их представление в UITableView
Это мои два класса:
// ScanTableView.swift
import UIKit
class ScanTableView: UITableViewController {
@IBOutlet var scanTableView: UITableView!
var bluetoothManager = BluetoothManager?()
var tableViewScanTime = 5
var timer1: NSTimer!
override func viewDidLoad() {
super.viewDidLoad()
self.refreshControl!.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let _ = bluetoothManager?.peripheralArray.count {
return bluetoothManager!.peripheralArray.count
}
else {
return 0
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = scanTableView.dequeueReusableCellWithIdentifier("scanCell",forIndexPath: indexPath)
cell.textLabel!.text = bluetoothManager!.peripheralArray[indexPath.row].name
cell.detailTextLabel!.text = bluetoothManager!.peripheralArray[indexPath.row].RSSI
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
bluetoothManager!.selectedPeripheral = bluetoothManager!.peripheralArray[indexPath.row]
bluetoothManager!.connectPeripheral(bluetoothManager!.selectedPeripheral!)
}
func refresh() {
scanTableView.userInteractionEnabled = false
timer1 = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "scanTableViewRefresh", userInfo: nil, repeats: true)
bluetoothManager = BluetoothManager()
}
func scanTableViewRefresh() {
scanTableView.reloadData()
tableViewScanTime--
if tableViewScanTime <= 0 {
timer1.invalidate()
bluetoothManager!.CBmanager.stopScan()
print("StopScan")
tableViewScanTime = 5
bluetoothManager!.peripheralArray.sortInPlace({$0.RSSI < $1.RSSI})
self.refreshControl!.endRefreshing()
self.scanTableView.userInteractionEnabled = true
}
}
}
// BluetoothManager.swift
import UIKit
import CoreBluetooth
class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
struct BluetoothPeripheral {
let name: String
let UUID: String
let RSSI: String
let peripheral: CBPeripheral
init(name: String, UUID: String, RSSI: NSNumber, peripheral: CBPeripheral) {
self.name = "\(name)"
self.UUID = "\(UUID)"
self.RSSI = "\(RSSI)"
self.peripheral = peripheral
}
}
let DEVICE_NAME:String! = "TEST"
//Creat an instance of ScanTableView Class
var scanTableView: ScanTableView()
var peripheralArray: [BluetoothPeripheral] = []
var selectedPeripheral: BluetoothPeripheral?
var characteristicArray: [CBCharacteristic] = []
var CBmanager: CBCentralManager = CBCentralManager()
var measurementValue: [[AnyObject?]] = [[]]
//Basic functions
override init() {
super.init()
CBmanager = CBCentralManager(delegate: self, queue: nil)
}
func connectPeripheral(selectedPeripheral: BluetoothPeripheral) {
CBmanager.connectPeripheral(selectedPeripheral.peripheral, options: nil)
}
func disconnectPeripheral(selectedPeripheral: BluetoothPeripheral) {
for characteristic in characteristicArray {
selectedPeripheral.peripheral.setNotifyValue(false, forCharacteristic: characteristic as CBCharacteristic)
}
CBmanager.cancelPeripheralConnection(selectedPeripheral.peripheral)
}
func ScanForPeripherals() {
CBmanager.scanForPeripheralsWithServices(nil, options: nil)
print("Scanning")
}
func centralManagerDidUpdateState(central: CBCentralManager) {
switch(central.state) {
case .PoweredOn:
CBmanager.scanForPeripheralsWithServices(nil, options: nil)
print("scan")
case .PoweredOff, .Resetting, .Unauthorized, .Unsupported, .Unknown:
peripheralArray.removeAll()
//This invokes an exception
//scanTableView.scanTableView.reloadData()
print("NO BLE!")
}
}
func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {
let UUID = "\(peripheral.identifier)".substringFromIndex("\(peripheral.identifier)".startIndex.advancedBy(31))
if let peripheralName = peripheral.name {
if peripheralName.containsString(DEVICE_NAME) {
peripheralArray.append(BluetoothPeripheral(name: peripheral.name!, UUID: UUID, RSSI: RSSI, peripheral: peripheral))
print(peripheralArray)
}
}
}
func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral) {
print("Connected")
measurementValue.removeAll()
peripheral.delegate = self
selectedPeripheral!.peripheral.discoverServices(nil)
}
func centralManager(central: CBCentralManager, didFailToConnectPeripheral peripheral: CBPeripheral, error: NSError?) {
print("Fail")
}
func centralManager(central: CBCentralManager, willRestoreState dict: [String : AnyObject]) {
print("Restore")
}
func centralManager(central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: NSError?) {
print("Disconnected")
}
func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) {
for service in peripheral.services! {
peripheral.discoverCharacteristics(nil, forService: service)
}
}
func peripheral(peripheral: CBPeripheral, didDiscoverCharacteristicsForService service: CBService, error: NSError?) {
for characteristic in service.characteristics as [CBCharacteristic]!{
if characteristic.properties.contains(CBCharacteristicProperties.Notify) {
peripheral.discoverDescriptorsForCharacteristic(characteristic)
peripheral.setNotifyValue(true, forCharacteristic: characteristic)
}
}
}
func peripheral(peripheral: CBPeripheral, didUpdateNotificationStateForCharacteristic characteristic: CBCharacteristic, error: NSError?) {
if characteristic.isNotifying {
characteristicArray.append(characteristic as CBCharacteristic)
peripheral.readValueForCharacteristic(characteristic)
}
}
func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) {
//Store new characteristic values
}
}
Теперь мои вопросы:
Показанные код работает, но я не в состоянии взаимодействовать между двумя классы. Например, я хотел бы перезагрузить открытый ScanTableView из моего класса BluetoothManager. Это невозможно ... каждый раз, когда я пытаюсь это сделать, я получаю исключение, которое я бы разворачивал. Зачем? Существуют ли различия между «нормальными» классами и классами, отображаемыми в графическом интерфейсе (UITableView, UIView ...)? Я задокументировал строку исключений ...
Было бы очень приятно, если бы кто-нибудь мог объяснить мне, что делать в таких ситуациях :).
Я рад за любые предложения или улучшения!
Можете указать, какая именно строка дает вам ошибку? Вместо использования NSTimer было бы лучше либо установить контроллер табличного представления в качестве делегата для вашего диспетчера Bluetooth, либо создать протокол, чтобы менеджер Bluetooth мог сообщить контроллеру таблицы о недавно обнаруженных устройствах или использовать диспетчер Bluetooth для использования NSNotification для консультирования заинтересованные классы об изменениях – Paulw11
В середине второго класса я прокомментировал 'scanTableView.scanTableView.reloadData()' out. Эта часть вызывает исключение. Я хотел бы использовать модуль NSTimer, чтобы «контролировать», как долго я ищу любые устройства. Поэтому в этом случае я просто ищу 5 секунд. Я не хочу использовать модуль NSNotification, чтобы избежать путаницы с кодом ... Я думаю, у меня есть проблема с правильным экземпляром моего ScanTableView. Я попробовал это с помощью «storyboard.instantiateViewControllerWithIdentifier» («scanTableViewIdentifier») как! ScanTableView ", но без каких-либо успехов. – Passe
Если вы не хотите использовать NSNotification, вам нужно будет использовать протокол и делегирование.Ваш менеджер Bluetooth не может создать экземпляр ScanTableView нового экземпляра, он должен связываться с тем, который уже существует, и это будет тот контроллер, который настроил себя как делегат менеджера bluetooth. – Paulw11