我试图找到一种方法来扫描BLE设备并将它们呈现在UITableView中。 BLE设备的扫描,连接,读写功能清晰可行!所以我的问题集中在'ScanTableView'和'BletoothManager'类之间的交互。
这是我的两个班级:
// 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
}
}
现在我的问题:
显示的代码有效,但我无法在两个类之间进行交互。 例如,我想从我的BluetoothManager类重新加载我打开的ScanTableView。这是不可能的...每次当我尝试这个时,我得到一个例外,我将解开一个可选项。为什么? “普通”类和GUI中显示的类(UITableView,UIView ...)之间是否存在任何差异?我记录了例外行......
如果有人能解释我在这种情况下该做什么,那将是非常好的:)。
我很高兴有任何建议或改进!
答案 0 :(得分:1)
就像@ paulw11所说,我必须创建一个委托协议:
protocol BluetoothDelegate: class {
func ReloadView()
}
这个'ReloadView'方法在我的ScanTableView类中声明:
func ReloadView() {
scanTableView.reloadData()
}
现在,我不得不做一些额外的事情:
就是这样!