问题
I've been having issues converting an Objective-C snippet to Swift that uses NSData
and CoreBluetooth
. I have looked at this question and a couple others dealing with NSData
in Swift but haven't had any success.
Objective-C Snippet:
- (CGFloat) minTemperature
{
CGFloat result = NAN;
int16_t value = 0;
// characteristic is a CBCharacteristic
if (characteristic) {
[[characteristic value] getBytes:&value length:sizeof (value)];
result = (CGFloat)value / 10.0f;
}
return result;
}
What I have so far in Swift (not working):
func minTemperature() -> CGFloat {
let bytes = [UInt8](characteristic?.value)
let pointer = UnsafePointer<UInt8>(bytes)
let fPointer = pointer.withMemoryRebound(to: Int16.self, capacity: 2) { return $0 }
value = Int16(fPointer.pointee)
result = CGFloat(value / 10) // not correct value
return result
}
Does the logic look wrong here? Thanks!
回答1:
One error is in
let fPointer = pointer.withMemoryRebound(to: Int16.self, capacity: 2) { return $0 }
because the rebound pointer $0
is only valid inside the closure and must
not be passed to the outside. Also the capacity should be 1
for a
single Int16
value. Another problem is the integer division in
result = CGFloat(value / 10)
which truncates the result (as already observed by the4kman).
Creating an [UInt8]
array from the data is not necessary, the
withUnsafeBytes()
method of Data
can be used instead.
Finally you could return nil
(instead of "not a number") if no
characteristic value is given:
func minTemperature() -> CGFloat? {
guard let value = characteristic?.value else {
return nil
}
let i16val = value.withUnsafeBytes { (ptr: UnsafePointer<Int16>) in
ptr.pointee
}
return CGFloat(i16val) / 10.0
}
回答2:
You should make the return value optional and check if characteristic
is nil in the beginning with a guard
. You should also explicitly convert the value to CGFloat
, then divide it by 10.
func minTemperature() -> CGFloat? {
guard characteristic != nil else {
return nil
}
let bytes = [UInt8](characteristic!.value)
let pointer = UnsafePointer<UInt8>(bytes)
let fPointer = pointer.withMemoryRebound(to: Int16.self, capacity: 2) { return $0 }
let value = Int16(fPointer.pointee)
result = CGFloat(value) / 10
return result
}
来源:https://stackoverflow.com/questions/45287488/trouble-converting-nsdata-objective-c-code-to-swift