目标C到Swift代码转换,似乎无法正确处理在Swift中的字节

我正在研究一个简单的Swift蓝牙心率监视器iOS应用程序。 我发现这个具有客观的C代码的伟大的教程。 我已经将其转换为Swift,并从我的心率监视器获取数据。 我的问题是,我似乎无法正确访问和转换在Swift中的字节数据。

Objective C代码如下:

// 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的types为UnsafePointer<UInt8> ,您可以像在(Objective-)C中那样访问它:

 if (reportData[0] & 0x01) == 0 { ... } 

下一个,

 bpm = reportData[1]; 

在Swift中几乎是一样的。 你必须显式地从UInt8转换为UInt16因为 – 不像(Objective-)C – Swift不会在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) } // ... } 

请注意,你的大部分variables可以用let声明为常量 ,而不是var 。 代替

 bpm = CFSwapInt16LittleToHost(bpm) 

您也可以使用littleEndian:构造函数,它可用于所有整数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 } ) } // ... }