此篇主要是如何顯示藍芽裝置
結合之前搜尋藍芽裝置與 TableView分為兩個群組的文章做個整合.
Step 1: 建立BtDelegate protocol
BtDelegate 主要是將搜尋到的藍芽裝置, 傳回給上層UI
1 2 3 4 5
| import Foundation
protocol BtDelegate { func findBtDevice(name: String?) }
|
Step 2: BtManager 搜尋到裝置後, 通知上層UI
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class BtManager : NSObject { var mCBCentralManager: CBCentralManager!
var delegate : BtDelegate? func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) { print("Device: \(peripheral.name) : \(peripheral.identifier.UUIDString)");
if (!isAlreadyFound(peripheral.identifier.UUIDString)) { insertFoundDevice(peripheral.identifier.UUIDString, newName: peripheral.name); delegate!.findBtDevice(peripheral.name); } else { print("This Device is discovered: \(peripheral.identifier.UUIDString)"); } }
|
Step 3: ViewController 繼承 BtDelegate, 並設定給 BtManager
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class ViewController: UIViewController { var mBtManager : BtManager!;
override func viewDidLoad() { super.viewDidLoad() mBtManager = BtManager(); mBtManager.delegate = self; } extension ViewController: BtDelegate { func findBtDevice(name: String?) { print("Find Device: \(name)"); } } }
|
Step 4: 顯示於TableView 上
UITableView 與程式建立連結
監聽TableView Data Change
1
| mDeviceTableView.dataSource = self;
|
插入資料到TableViewCell 中
在此例子中, 我們將新資料插到最後一排.
首先先在 BtManage.swift 中取得目前搜尋到裝置的個數
1 2 3 4 5 6
| class BtManager : NSObject { var mFoundDevices : Dictionary<String , BtDevice>!; func getFoundDevicesSize() -> Int { return mFoundDevices.count; } }
|
插入資料 (由於搜尋到的裝置我們放在Group 1 , 所以 inSection : 0)
1 2 3 4 5 6 7 8 9
| extension ViewController: BtDelegate { func findBtDevice(name: String?) { print("Find Device: \(name)");
let indexPath = NSIndexPath( forRow: mBtManager.getFoundDevicesSize()-1, inSection: 0); mDeviceTableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic); } }
|
設定目前Row個數
1 2 3 4 5 6 7 8 9 10
| func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch (section) { case 0: return mBtManager.getFoundDevicesSize(); case 1: return 0; default: return 0; } }
|
設定TableViewCell內容
首先在BtManager.swift中, 取得BT Device Name
1 2 3 4 5 6 7 8 9
| func getFoundDeviceName(index: Int) -> String? { print("index: \(index)"); let keyIndex = mFoundDevices.startIndex.advancedBy(index); print("keyIndex: \(keyIndex)"); let key = mFoundDevices.keys[keyIndex]; print("key: \(key)"); let btDevice = mFoundDevices[key]!; return btDevice.name; }
|
設定內容
1 2 3 4 5 6 7 8 9 10 11 12 13
| func tableView(tableView: UITableView,cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var deviceName : String?; switch(indexPath.section) { case 0: deviceName = mBtManager.getFoundDeviceName(indexPath.row); default: deviceName = "Unknow"; }
let cell: UITableViewCell = UITableViewCell( style:UITableViewCellStyle.Subtitle, reuseIdentifier: "deviceCell"); cell.textLabel?.text = "Device Name: \(deviceName)"; return cell; }
|
Step 5: 重新搜尋時, 必須清空TableView內容
1 2 3 4 5 6 7 8 9 10
| func startScan() { mLoadingView.startAnimating(); mBtManager.startToScan(); cleanAllFoundDevices(); changeToStopButton(); }
private func cleanAllFoundDevices() { mDeviceTableView.reloadData(); }
|
Source Code
BtDevice class 的定義可參考
iOS - 搜尋藍芽裝置 Part II - 避免搜尋到重複的裝置
BtManager.swift1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| import Foundation import CoreBluetooth
class BtManager : NSObject { var mCBCentralManager: CBCentralManager!
var delegate : BtDelegate? var mFoundDevices : Dictionary<String , BtDevice>!;
override init() { super.init(); initCBCentralManager(); mFoundDevices = [String : BtDevice](); } internal func initCBCentralManager() { mCBCentralManager = CBCentralManager(delegate: self, queue: nil, options: [CBCentralManagerOptionShowPowerAlertKey: true]); }
func isScanning() -> Bool { return mCBCentralManager.isScanning; }
func startToScan() { if (mCBCentralManager.state == CBCentralManagerState.PoweredOff) { print("state is off"); initCBCentralManager(); } else { if (isScanning()) { print("state is scanning"); } else { clearAllFoundDevices(); mCBCentralManager.scanForPeripheralsWithServices(nil, options: nil); print("start to scan: \(isScanning())"); } } }
func stopScanning() { mCBCentralManager.stopScan(); } func getFoundDevicesSize() -> Int { return mFoundDevices.count; }
func getFoundDeviceName(index: Int) -> String? { print("index: \(index)"); let keyIndex = mFoundDevices.startIndex.advancedBy(index); print("keyIndex: \(keyIndex)"); let key = mFoundDevices.keys[keyIndex]; print("key: \(key)"); let btDevice = mFoundDevices[key]!; return btDevice.name; } }
extension BtManager : CBCentralManagerDelegate { func centralManagerDidUpdateState(central: CBCentralManager) { switch (central.state) { case CBCentralManagerState.PoweredOn: print("state On"); case CBCentralManagerState.PoweredOff: print("state Off"); case CBCentralManagerState.Unknown: fallthrough; default: print("state Unknow"); } }
func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) { print("Device: \(peripheral.name) : \(peripheral.identifier.UUIDString)");
if (!isAlreadyFound(peripheral.identifier.UUIDString)) { insertFoundDevice(peripheral.identifier.UUIDString, newName: peripheral.name); delegate!.findBtDevice(peripheral.name); } else { print("This Device is discovered: \(peripheral.identifier.UUIDString)"); } }
internal func isAlreadyFound(uuid : String!) -> Bool { return mFoundDevices[uuid] != nil; }
internal func insertFoundDevice(newUuid: String!, newName: String?) { let btDevice = BtDevice(uuid: newUuid, name: newName); mFoundDevices[newUuid] = btDevice; }
internal func clearAllFoundDevices() { mFoundDevices.removeAll(); } }
|
ViewController.swift1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
| import UIKit
class ViewController: UIViewController { var mBtManager : BtManager!; @IBOutlet weak var mLoadingView: UIActivityIndicatorView! @IBOutlet weak var mDeviceTableView: UITableView!
override func viewDidLoad() { super.viewDidLoad() mBtManager = BtManager(); mBtManager.delegate = self; mLoadingView.stopAnimating(); mLoadingView.hidesWhenStopped = true; mDeviceTableView.dataSource = self; }
override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() }
@IBAction func prepareScan(sender: AnyObject) { startScan(); }
func startScan() { mLoadingView.startAnimating(); mBtManager.startToScan(); cleanAllFoundDevices(); changeToStopButton(); }
private func cleanAllFoundDevices() { mDeviceTableView.reloadData(); } func stopScan() { mLoadingView.stopAnimating(); mBtManager.stopScanning(); changeToScanButton(); }
private func changeToStopButton() { let stopScanningButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Stop, target: self, action: #selector(ViewController.stopScan)); self.navigationItem.rightBarButtonItem = stopScanningButton; }
private func changeToScanButton() { let scanButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Search, target: self, action: #selector(ViewController.startScan)); self.navigationItem.rightBarButtonItem = scanButton; } }
extension ViewController : UITableViewDataSource { func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 2; }
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { switch (section) { case 0: return "Found Devices:"; case 1: return "Connected Devices:"; default: return "Unknow"; } }
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch (section) { case 0: return mBtManager.getFoundDevicesSize(); case 1: return 0; default: return 0; } }
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var deviceName : String?; switch(indexPath.section) { case 0: deviceName = mBtManager.getFoundDeviceName(indexPath.row); default: deviceName = "Unknow"; }
let cell: UITableViewCell = UITableViewCell( style:UITableViewCellStyle.Subtitle, reuseIdentifier: "deviceCell");
cell.textLabel?.text = "Device Name: \(deviceName)"; return cell; } }
extension ViewController: BtDelegate { func findBtDevice(name: String?) { print("Find Device: \(name)");
let indexPath = NSIndexPath(forRow: mBtManager.getFoundDevicesSize()-1, inSection: 0);
mDeviceTableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic); } }
|