2
我試圖找到一種方法來掃描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
}
}
現在我的問題:
所顯示的代碼工作,但我不能在兩者之間進行交互類。 例如,我想重新從我的BluetoothManager類中打開ScanTableView。這是不可能的...每次當我嘗試這個時,我會得到一個異常,我會打開一個可選的。爲什麼? '正常'類和GUI中顯示的類(UITableView,UIView ...)之間是否有區別?我記錄了異常行...
這將是非常好的,如果任何人都可以解釋我在這種情況下做什麼:)。
我很高興有任何建議或改進!
你能指出哪條線給你錯誤嗎?而不是使用NSTimer,最好將您的表格視圖控制器設置爲您的藍牙管理器的代表,並創建一個協議,以便藍牙管理器可以建議桌面控制器關於新發現的設備,或讓藍牙管理器使用NSNotification建議感興趣的類有關更改 – Paulw11
在第二課中,我評論了'scanTableView.scanTableView.reloadData()'。這部分調用一個異常。我想使用NSTimer模塊來「控制」我搜索任何設備的時間。所以在這種情況下我只搜索了5秒。我不想使用NSNotification模塊,以避免混淆代碼......我想,我的ScanTableView的正確實例有問題。我嘗試了'storyboard.instantiateViewControllerWithIdentifier(「scanTableViewIdentifier」)as! ScanTableView「,但沒有任何成功。 – Passe
如果您不想使用NSNotification,那麼您將需要使用協議和委派。您的藍牙管理器無法實例化ScanTableView的新實例,它需要與已存在的實例進行通信,並且該視圖控制器將自己設置爲藍牙管理器的代表 – Paulw11