我试图找到一种方法来扫描 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。这是不可能的......每次我尝试这个时,我都会得到一个异常(exception),我会解开一个可选的。为什么? “普通”类和 GUI 中显示的类(UITableView、UIView...)之间有什么区别吗?我记录了异常行...
如果有人能向我解释在这种情况下该怎么做,那就太好了:)。
我很乐意提出任何建议或改进!
最佳答案
就像@paulw11 说的,我必须创建一个委托(delegate)协议(protocol):
protocol BluetoothDelegate: class {
func ReloadView()
}
此“ReloadView”方法在我的 ScanTableView 类中声明:
func ReloadView() {
scanTableView.reloadData()
}
现在,我必须做一些额外的事情:
就是这样!
关于swift - 扫描 BLE 设备并将它们呈现在 UITableView 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35379136/
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
简而言之错误:NOTE:Gem::SourceIndex#add_specisdeprecated,useSpecification.add_spec.Itwillberemovedonorafter2011-11-01.Gem::SourceIndex#add_speccalledfrom/opt/local/lib/ruby/site_ruby/1.8/rubygems/source_index.rb:91./opt/local/lib/ruby/gems/1.8/gems/rails-2.3.8/lib/rails/gem_dependency.rb:275:in`==':und
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的
Heroku支持人员告诉我,为了在我的Web应用程序中使用自定义字体(未安装在系统中,您可以在bash控制台中使用fc-list查看已安装的字体)我必须部署一个包含所有字体的.fonts文件夹里面的字体。问题是我不知道该怎么做。我的意思是,我不知道文件名是否必须遵循heroku的任何特殊模式,或者我必须在我的代码中做一些事情来考虑这种字体,或者如果我将它包含在文件夹中它是自动的......事实是,我尝试以不同的方式更改字体的文件名,但根本没有使用该字体。为了提供更多详细信息,我们使用字体的过程是将PDF转换为图像,更具体地说,使用rghostgem。并且最终图像根本不使用自定义字体。在
Devise是一个Ruby库,它为我提供了这个User类:classUser当写入:confirmable时,注册时会发送一封确认邮件。上周我不得不批量创建300个用户,所以我在恢复之前注释掉了:confirmable几分钟。现在我正在为用户批量创建创建一个UI,因此我需要即时添加/删除:confirmable。(我也可以直接修改Devise的源码,但我宁愿不去调和它)问题:如何即时添加/删除:confirmable? 最佳答案 WayneConrad的解决方案:user=User.newuser.skip_confirmation
有没有办法跳过CSV文件的第一行,让第二行作为标题?我有一个CSV文件,第一行是日期,第二行是标题,所以我需要能够在遍历它时跳过第一行。我尝试使用slice但它会将CSV转换为数组,我真的很想将其读取为CSV,以便我可以利用header。 最佳答案 根据您的数据,您可以使用另一种方法和skip_lines-option此示例跳过所有以#开头的行require'csv'CSV.parse(DATA.read,:col_sep=>';',:headers=>true,:skip_lines=>/^#/#Markcomments!)do|
我有1.8.6附带的VanillaMacOSXLeopard。我是RoR的新手,所以会学习网上的教程。在使用更高版本的Ruby时,我是否可能会发现遵循它们的问题?我目前正在查看提到1.8.6和1.8.7的这个-http://www.railstutorial.org/book 最佳答案 RoR教程对两者都适用,但如果您正在学习Ruby,则应该学习1.9。Rails3将不支持1.8.6,所以我会选择1.8.7或1.9。我还推荐使用RVM在Ruby版本之间切换。 关于ruby-on-rail
我有时遇到过Array(value)、String(value)和Integer(value)形式的转换。在我看来,这些只是调用相应的value.to_a、value.to_s或value.to_i方法的语法糖。所以我想知道:这些是在哪里/如何定义的?我在对象、模块、类等中找不到它们是否有任何常见场景更适合使用这些而不是相应/底层的to_X方法?这些可以用于泛型强制转换吗?也就是说,我可以按照[Integer,String,Array].each{|klass|klass.do_generic_coercion(foo)}?(...不,我真的不想那样做;我知道我想要的类型,但我希望避免
我想扫描未知数量的行,直到扫描完所有行。我如何在ruby中做到这一点?例如:putreturnsbetweenparagraphsforlinebreakadd2spacesatend_italic_or**bold**输入不是来自"file",而是通过STDIN。 最佳答案 在ruby中有很多方法可以做到这一点。大多数情况下,您希望一次处理一行,例如,您可以使用whileline=getsend或STDIN.each_linedo|line|end或者通过使用-n开关运行ruby,例如,这意味着上述循环之一(在每次迭代中将