目标C到Swift代码转换,似乎无法在Swift中正确处理字节 [英] Objective C to Swift code conversion, can't seem to treat bytes correctly in Swift
问题描述
我正在开发一款简单的Swift蓝牙心率监测器iOS App。我找到了这个伟大的教程,它有目标C码。我已将它转换为Swift,我从心率监测器获取数据。我的问题是我似乎无法在Swift中正确访问和转换字节数据。
I'm working on a simple Swift bluetooth heart rate monitor iOS App. I found this great tutorial which has objective C code. I've converted it to Swift and I'm getting data from my heart rate monitor. My problem is that I can't seem to correctly access and convert the byte data in Swift.
这是Objective C代码:
Here's the Objective C code:
// Instance method to get the heart rate BPM information
- (void) getHeartBPMData:(CBCharacteristic *)characteristic error:(NSError *)error
{
// Get the Heart Rate Monitor BPM
NSData *data = [characteristic value]; // 1
const uint8_t *reportData = [data bytes];
uint16_t bpm = 0;
if ((reportData[0] & 0x01) == 0) { // 2
// Retrieve the BPM value for the Heart Rate Monitor
bpm = reportData[1];
}
else {
bpm = CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[1])); // 3
}
// Display the heart rate value to the UI if no error occurred
if( (characteristic.value) || !error ) { // 4
self.heartRate = bpm;
self.heartRateBPM.text = [NSString stringWithFormat:@"%i bpm", bpm];
self.heartRateBPM.font = [UIFont fontWithName:@"Futura-CondensedMedium" size:28];
[self doHeartBeat];
self.pulseTimer = [NSTimer scheduledTimerWithTimeInterval:(60. / self.heartRate) target:self selector:@selector(doHeartBeat) userInfo:nil repeats:NO];
}
return;
}
这是Swift代码:
func peripheral(peripheral: CBPeripheral!,
didUpdateValueForCharacteristic characteristic: CBCharacteristic!,
error: NSError!) -> String
{
// Get the Heart Rate Monitor BPM
var data = characteristic.value
var reportData = data.bytes
var bpm : UInt16
var rawByte : UInt8
var outputString = ""
rawByte = UInt8(reportData[0])
bpm = 0
if ((rawByte & 0x01) == 0) { // 2
// Retrieve the BPM value for the Heart Rate Monitor
bpm = UInt16( reportData[4] )
}
else {
bpm = CFSwapInt16LittleToHost(UInt16(reportData[1]))
}
outputString = String(bpm)
return outputString
}
推荐答案
const uint8_t *reportData = [data bytes];
转换为
let reportData = UnsafePointer<UInt8>(data.bytes)
然后 reportData
的类型为 UnsafePointer< UInt8>
,您可以在(目标 - )C中访问它:
Then reportData
has the type UnsafePointer<UInt8>
and you can access it as in (Objective-)C:
if (reportData[0] & 0x01) == 0 { ... }
接下来,
bpm = reportData[1];
在Swift中几乎相同。你必须明确地从 UInt8
转换为
UInt16
,因为 - 与(目标 - )C - Swift不同不能在类型之间隐式转换:
is almost identical in Swift. You have to convert explicitly from UInt8
to
UInt16
because – unlike (Objective-)C – Swift does not implicitly convert between types:
bpm = UInt16(reportData[1])
汇总:
func getHeartBPMData(characteristic: CBCharacteristic!) {
let data = characteristic.value
let reportData = UnsafePointer<UInt8>(data.bytes)
var bpm : UInt16
if (reportData[0] & 0x01) == 0 {
bpm = UInt16(reportData[1])
} else {
bpm = UnsafePointer<UInt16>(reportData + 1)[0]
bpm = CFSwapInt16LittleToHost(bpm)
}
// ...
}
请注意,大多数变量都可以声明为常量,其中 let
,而不是
VAR
。而不是
Note that most of your variables can be declared as constants with let
, instead
of var
. Instead of
bpm = CFSwapInt16LittleToHost(bpm)
您也可以使用 littleEndian:
构造函数,对于所有整数类型,可以使用
:
you can alternatively use the littleEndian:
constructor which is available
for all integer types:
bpm = UInt16(littleEndian: bpm)
Swift 3/4更新:
func getHeartBPMData(characteristic: CBCharacteristic) {
guard let reportData = characteristic.value else {
return
}
let bpm : UInt16
if (reportData[0] & 0x01) == 0 {
bpm = UInt16(reportData[1])
} else {
bpm = UInt16(littleEndian: reportData.subdata(in: 1..<3).withUnsafeBytes { $0.pointee } )
}
// ...
}
这篇关于目标C到Swift代码转换,似乎无法在Swift中正确处理字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!