Skip to content

Commit

Permalink
Refactoring overhaul
Browse files Browse the repository at this point in the history
  • Loading branch information
rhummelmose committed Sep 4, 2015
1 parent 67d6969 commit b37ae11
Show file tree
Hide file tree
Showing 12 changed files with 263 additions and 133 deletions.
28 changes: 18 additions & 10 deletions BluetoothKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
objects = {

/* Begin PBXBuildFile section */
C66888AD1B978181003C8DBB /* BKDiscovery.swift in Sources */ = {isa = PBXBuildFile; fileRef = C66888AC1B978181003C8DBB /* BKDiscovery.swift */; settings = {ASSET_TAGS = (); }; };
C66888AF1B984792003C8DBB /* BKConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C66888AE1B984792003C8DBB /* BKConfiguration.swift */; settings = {ASSET_TAGS = (); }; };
C66888B11B984AB7003C8DBB /* BKPeripheralConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C66888B01B984AB7003C8DBB /* BKPeripheralConfiguration.swift */; settings = {ASSET_TAGS = (); }; };
C67A22361B8C49CC00CB74CE /* BKConnectionAttempt.swift in Sources */ = {isa = PBXBuildFile; fileRef = C67A22351B8C49CC00CB74CE /* BKConnectionAttempt.swift */; };
C67A22711B8C7EF300CB74CE /* BKPeripheral.swift in Sources */ = {isa = PBXBuildFile; fileRef = C67A22701B8C7EF300CB74CE /* BKPeripheral.swift */; };
C67A22731B8C80C300CB74CE /* BKAvailability.swift in Sources */ = {isa = PBXBuildFile; fileRef = C67A22721B8C80C300CB74CE /* BKAvailability.swift */; };
Expand All @@ -21,13 +24,15 @@
C687E3B81B8B4A2800B702D8 /* BKRemotePeripheral.swift in Sources */ = {isa = PBXBuildFile; fileRef = C687E3AC1B8B4A2800B702D8 /* BKRemotePeripheral.swift */; };
C687E3B91B8B4A2800B702D8 /* BKConnectionPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = C687E3AD1B8B4A2800B702D8 /* BKConnectionPool.swift */; };
C687E3BA1B8B4A2800B702D8 /* BKScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = C687E3AE1B8B4A2800B702D8 /* BKScanner.swift */; };
C687E3BB1B8B4A2800B702D8 /* BKService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C687E3AF1B8B4A2800B702D8 /* BKService.swift */; };
C687E3C41B8B4CF100B702D8 /* BluetoothKit.h in Headers */ = {isa = PBXBuildFile; fileRef = C687E3C31B8B4CF100B702D8 /* BluetoothKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
C6BFB2921B95885D00AB5CAE /* BKScanChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6BFB2911B95885D00AB5CAE /* BKScanChange.swift */; };
C6BFB2921B95885D00AB5CAE /* BKDiscoveriesChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6BFB2911B95885D00AB5CAE /* BKDiscoveriesChange.swift */; };
C6BFB2941B959C8800AB5CAE /* BKContinuousScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6BFB2931B959C8800AB5CAE /* BKContinuousScanner.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
C66888AC1B978181003C8DBB /* BKDiscovery.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BKDiscovery.swift; sourceTree = "<group>"; };
C66888AE1B984792003C8DBB /* BKConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BKConfiguration.swift; sourceTree = "<group>"; };
C66888B01B984AB7003C8DBB /* BKPeripheralConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BKPeripheralConfiguration.swift; sourceTree = "<group>"; };
C67A22351B8C49CC00CB74CE /* BKConnectionAttempt.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BKConnectionAttempt.swift; sourceTree = "<group>"; };
C67A22701B8C7EF300CB74CE /* BKPeripheral.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BKPeripheral.swift; sourceTree = "<group>"; };
C67A22721B8C80C300CB74CE /* BKAvailability.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BKAvailability.swift; sourceTree = "<group>"; };
Expand All @@ -44,9 +49,8 @@
C687E3AC1B8B4A2800B702D8 /* BKRemotePeripheral.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BKRemotePeripheral.swift; sourceTree = "<group>"; };
C687E3AD1B8B4A2800B702D8 /* BKConnectionPool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BKConnectionPool.swift; sourceTree = "<group>"; };
C687E3AE1B8B4A2800B702D8 /* BKScanner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BKScanner.swift; sourceTree = "<group>"; };
C687E3AF1B8B4A2800B702D8 /* BKService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BKService.swift; sourceTree = "<group>"; };
C687E3C31B8B4CF100B702D8 /* BluetoothKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BluetoothKit.h; sourceTree = "<group>"; };
C6BFB2911B95885D00AB5CAE /* BKScanChange.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BKScanChange.swift; sourceTree = "<group>"; };
C6BFB2911B95885D00AB5CAE /* BKDiscoveriesChange.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BKDiscoveriesChange.swift; sourceTree = "<group>"; };
C6BFB2931B959C8800AB5CAE /* BKContinuousScanner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BKContinuousScanner.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -95,18 +99,20 @@
C687E3A71B8B4A2800B702D8 /* BKCBPeripheralDelegateProxy.swift */,
C67A22771B8C86C800CB74CE /* BKCBPeripheralManagerDelegateProxy.swift */,
C687E3A81B8B4A2800B702D8 /* BKCental.swift */,
C6BFB2911B95885D00AB5CAE /* BKScanChange.swift */,
C687E3AB1B8B4A2800B702D8 /* BKCentralStateMachine.swift */,
C66888AE1B984792003C8DBB /* BKConfiguration.swift */,
C67A22351B8C49CC00CB74CE /* BKConnectionAttempt.swift */,
C687E3AD1B8B4A2800B702D8 /* BKConnectionPool.swift */,
C6BFB2931B959C8800AB5CAE /* BKContinuousScanner.swift */,
C6BFB2911B95885D00AB5CAE /* BKDiscoveriesChange.swift */,
C66888AC1B978181003C8DBB /* BKDiscovery.swift */,
C67A22701B8C7EF300CB74CE /* BKPeripheral.swift */,
C67A227B1B8CECB400CB74CE /* BKSendDataTask.swift */,
C66888B01B984AB7003C8DBB /* BKPeripheralConfiguration.swift */,
C67A22741B8C83D900CB74CE /* BKPeripheralStateMachine.swift */,
C67A22791B8CDC7D00CB74CE /* BKRemoteCentral.swift */,
C687E3AC1B8B4A2800B702D8 /* BKRemotePeripheral.swift */,
C687E3AE1B8B4A2800B702D8 /* BKScanner.swift */,
C6BFB2931B959C8800AB5CAE /* BKContinuousScanner.swift */,
C687E3AF1B8B4A2800B702D8 /* BKService.swift */,
C67A227B1B8CECB400CB74CE /* BKSendDataTask.swift */,
);
path = Source;
sourceTree = "<group>";
Expand Down Expand Up @@ -202,16 +208,18 @@
C687E3B81B8B4A2800B702D8 /* BKRemotePeripheral.swift in Sources */,
C67A22361B8C49CC00CB74CE /* BKConnectionAttempt.swift in Sources */,
C6BFB2941B959C8800AB5CAE /* BKContinuousScanner.swift in Sources */,
C66888AD1B978181003C8DBB /* BKDiscovery.swift in Sources */,
C687E3B21B8B4A2800B702D8 /* BKCBCentralManagerDelegateProxy.swift in Sources */,
C6BFB2921B95885D00AB5CAE /* BKScanChange.swift in Sources */,
C66888B11B984AB7003C8DBB /* BKPeripheralConfiguration.swift in Sources */,
C6BFB2921B95885D00AB5CAE /* BKDiscoveriesChange.swift in Sources */,
C67A22731B8C80C300CB74CE /* BKAvailability.swift in Sources */,
C687E3B31B8B4A2800B702D8 /* BKCBPeripheralDelegateProxy.swift in Sources */,
C67A227C1B8CECB400CB74CE /* BKSendDataTask.swift in Sources */,
C687E3B41B8B4A2800B702D8 /* BKCental.swift in Sources */,
C67A227A1B8CDC7D00CB74CE /* BKRemoteCentral.swift in Sources */,
C66888AF1B984792003C8DBB /* BKConfiguration.swift in Sources */,
C67A22711B8C7EF300CB74CE /* BKPeripheral.swift in Sources */,
C687E3B71B8B4A2800B702D8 /* BKCentralStateMachine.swift in Sources */,
C687E3BB1B8B4A2800B702D8 /* BKService.swift in Sources */,
C687E3BA1B8B4A2800B702D8 /* BKScanner.swift in Sources */,
C687E3B91B8B4A2800B702D8 /* BKConnectionPool.swift in Sources */,
);
Expand Down
50 changes: 29 additions & 21 deletions Example/Source/View Controllers/CentralViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import UIKit
import BluetoothKit
import CoreBluetooth

internal class CentralViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, BKCentralDelegate, AvailabilityViewController, RemotePeripheralViewControllerDelegate {

Expand All @@ -36,9 +37,9 @@ internal class CentralViewController: UIViewController, UITableViewDataSource, U
}

private let activityIndicatorBarButtonItem = UIBarButtonItem(customView: UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.White))
private let peripheralsTableView = UITableView()
private var peripherals = [BKRemotePeripheral]()
private let peripheralsTableViewCellIdentifier = "Peripheral Table View Cell Identifier"
private let discoveriesTableView = UITableView()
private var discoveries = [BKDiscovery]()
private let discoveriesTableViewCellIdentifier = "Discoveries Table View Cell Identifier"
private let central = BKCentral()

// MARK: UIViewController Life Cycle
Expand All @@ -49,10 +50,10 @@ internal class CentralViewController: UIViewController, UITableViewDataSource, U
navigationItem.title = "Central"
navigationItem.rightBarButtonItem = activityIndicatorBarButtonItem
applyAvailabilityView()
peripheralsTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: peripheralsTableViewCellIdentifier)
peripheralsTableView.dataSource = self
peripheralsTableView.delegate = self
view.addSubview(peripheralsTableView)
discoveriesTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: discoveriesTableViewCellIdentifier)
discoveriesTableView.dataSource = self
discoveriesTableView.delegate = self
view.addSubview(discoveriesTableView)
applyConstraints()
startCentral()
}
Expand All @@ -72,7 +73,7 @@ internal class CentralViewController: UIViewController, UITableViewDataSource, U
// MARK: Functions

private func applyConstraints() {
peripheralsTableView.snp_makeConstraints { make in
discoveriesTableView.snp_makeConstraints { make in
make.top.equalTo(snp_topLayoutGuideBottom)
make.leading.trailing.equalTo(view)
make.bottom.equalTo(availabilityView.snp_top)
Expand All @@ -83,30 +84,36 @@ internal class CentralViewController: UIViewController, UITableViewDataSource, U
do {
central.delegate = self
central.addAvailabilityObserver(self)
try central.start()
let dataServiceUUID = NSUUID(UUIDString: "6E6B5C64-FAF7-40AE-9C21-D4933AF45B23")!
let dataServiceCharacteristicUUID = NSUUID(UUIDString: "477A2967-1FAB-4DC5-920A-DEE5DE685A3D")!
let configuration = BKConfiguration(dataServiceUUID: dataServiceUUID, dataServiceCharacteristicUUID: dataServiceCharacteristicUUID)
try central.startWithConfiguration(configuration)
} catch let error {
print("Error while starting: \(error)")
}
}

private func scan() {
central.scanContinuouslyWithChangeHandler({ changes, peripherals in
let indexPathsToRemove = changes.filter({ $0 == .Remove(remotePeripheral: nil) }).map({ NSIndexPath(forRow: self.peripherals.indexOf($0.remotePeripheral)!, inSection: 0) })
self.peripherals = peripherals
let indexPathsToInsert = changes.filter({ $0 == .Insert(remotePeripheral: nil) }).map({ NSIndexPath(forRow: self.peripherals.indexOf($0.remotePeripheral)!, inSection: 0) })
central.scanContinuouslyWithChangeHandler({ changes, discoveries in
let indexPathsToRemove = changes.filter({ $0 == .Remove(discovery: nil) }).map({ NSIndexPath(forRow: self.discoveries.indexOf($0.discovery)!, inSection: 0) })
self.discoveries = discoveries
let indexPathsToInsert = changes.filter({ $0 == .Insert(discovery: nil) }).map({ NSIndexPath(forRow: self.discoveries.indexOf($0.discovery)!, inSection: 0) })
if !indexPathsToRemove.isEmpty {
self.peripheralsTableView.deleteRowsAtIndexPaths(indexPathsToRemove, withRowAnimation: UITableViewRowAnimation.Automatic)
self.discoveriesTableView.deleteRowsAtIndexPaths(indexPathsToRemove, withRowAnimation: UITableViewRowAnimation.Automatic)
}
if !indexPathsToInsert.isEmpty {
self.peripheralsTableView.insertRowsAtIndexPaths(indexPathsToInsert, withRowAnimation: UITableViewRowAnimation.Automatic)
self.discoveriesTableView.insertRowsAtIndexPaths(indexPathsToInsert, withRowAnimation: UITableViewRowAnimation.Automatic)
}
for insertedDiscovery in changes.filter({ $0 == .Insert(discovery: nil) }) {
Logger.log("Discovery: \(insertedDiscovery)")
}
}, stateHandler: { newState in
if newState == .Scanning {
self.activityIndicator.startAnimating()
return
} else if newState == .Stopped {
self.peripherals.removeAll()
self.peripheralsTableView.reloadData()
self.discoveries.removeAll()
self.discoveriesTableView.reloadData()
}
self.activityIndicator.stopAnimating()
}, errorHandler: { error in
Expand All @@ -117,20 +124,21 @@ internal class CentralViewController: UIViewController, UITableViewDataSource, U
// MARK: UITableViewDataSource

internal func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return peripherals.count
return discoveries.count
}

internal func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(peripheralsTableViewCellIdentifier, forIndexPath: indexPath)
cell.textLabel?.text = peripherals[indexPath.row].name
let cell = tableView.dequeueReusableCellWithIdentifier(discoveriesTableViewCellIdentifier, forIndexPath: indexPath)
let discovery = discoveries[indexPath.row]
cell.textLabel?.text = discovery.localName != nil ? discovery.localName : discovery.remotePeripheral.name
return cell
}

// MARK: UITableViewDelegate

internal func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.userInteractionEnabled = false
central.connect(remotePeripheral: peripherals[indexPath.row]) { remotePeripheral, error in
central.connect(remotePeripheral: discoveries[indexPath.row].remotePeripheral) { remotePeripheral, error in
tableView.userInteractionEnabled = true
guard error == nil else {
print("Error connecting peripheral: \(error)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ internal class PeripheralViewController: UIViewController, AvailabilityViewContr
do {
peripheral.delegate = self
peripheral.addAvailabilityObserver(self)
try peripheral.startWithName(NSBundle.mainBundle().infoDictionary!["CFBundleName"] as? String)
let dataServiceUUID = NSUUID(UUIDString: "6E6B5C64-FAF7-40AE-9C21-D4933AF45B23")!
let dataServiceCharacteristicUUID = NSUUID(UUIDString: "477A2967-1FAB-4DC5-920A-DEE5DE685A3D")!
let localName = NSBundle.mainBundle().infoDictionary!["CFBundleName"] as? String
let configuration = BKPeripheralConfiguration(dataServiceUUID: dataServiceUUID, dataServiceCharacteristicUUID: dataServiceCharacteristicUUID, localName: localName)
try peripheral.startWithConfiguration(configuration)
Logger.log("Awaiting connections from remote centrals")
} catch let error {
print("Error starting: \(error)")
Expand Down
34 changes: 25 additions & 9 deletions Source/BKCental.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ public class BKCentral: BKCBCentralManagerStateDelegate, BKConnectionPoolDelegat

// MARK: Type Aliases

public typealias ScanProgressHandler = ((newDiscoveries: [BKRemotePeripheral]) -> Void)
public typealias ScanCompletionHandler = ((result: [BKRemotePeripheral]?, error: Error?) -> Void)
public typealias ContinuousScanChangeHandler = ((changes: [BKScanChange], peripherals: [BKRemotePeripheral]) -> Void)
public typealias ScanProgressHandler = ((newDiscoveries: [BKDiscovery]) -> Void)
public typealias ScanCompletionHandler = ((result: [BKDiscovery]?, error: Error?) -> Void)
public typealias ContinuousScanChangeHandler = ((changes: [BKDiscoveriesChange], discoveries: [BKDiscovery]) -> Void)
public typealias ContinuousScanStateHandler = ((newState: ContinuousScanState) -> Void)
public typealias ContinuousScanErrorHandler = ((error: Error) -> Void)
public typealias ConnectCompletionHandler = ((remotePeripheral: BKRemotePeripheral, error: Error?) -> Void)
Expand All @@ -74,23 +74,36 @@ public class BKCentral: BKCBCentralManagerStateDelegate, BKConnectionPoolDelegat
return singleton
}

public var availability: BKAvailability {
return BKAvailability(centralManagerState: centralManager.state)
public var availability: BKAvailability? {
if let centralManager = _centralManager {
return BKAvailability(centralManagerState: centralManager.state)
} else {
return nil
}
}

public var connectedRemotePeripherals: [BKRemotePeripheral] {
return connectionPool.connectedRemotePeripherals
}

public var configuration: BKConfiguration? {
return _configuration
}

public var centralManager: CBCentralManager? {
return _centralManager
}

public weak var delegate: BKCentralDelegate?
public var availabilityObservers = [BKWeakAvailabilityObserver]()

private var _configuration: BKConfiguration?
private let scanner = BKScanner()
private var continuousScanner: BKContinousScanner!
private let connectionPool = BKConnectionPool()
private var centralManagerDelegate: BKCBCentralManagerDelegateProxy!
private var stateMachine: BKCentralStateMachine!
private var centralManager: CBCentralManager!
private var _centralManager: CBCentralManager!

// MARK: Initialization

Expand All @@ -103,10 +116,12 @@ public class BKCentral: BKCBCentralManagerStateDelegate, BKConnectionPoolDelegat

// MARK: Public Functions

public func start() throws {
public func startWithConfiguration(configuration: BKConfiguration) throws {
do {
try stateMachine.handleEvent(.Start)
centralManager = CBCentralManager(delegate: centralManagerDelegate, queue: nil, options: nil)
_configuration = configuration
_centralManager = CBCentralManager(delegate: centralManagerDelegate, queue: nil, options: nil)
scanner.configuration = configuration
scanner.centralManager = centralManager
connectionPool.centralManager = centralManager
} catch let error {
Expand Down Expand Up @@ -184,7 +199,8 @@ public class BKCentral: BKCBCentralManagerStateDelegate, BKConnectionPoolDelegat
try stateMachine.handleEvent(.Stop)
interrupScan()
connectionPool.reset()
centralManager = nil
_configuration = nil
_centralManager = nil
} catch let error {
throw Error.InternalError(underlyingError: error)
}
Expand Down
Loading

0 comments on commit b37ae11

Please sign in to comment.