Swift - преобразование из UnsafePointer<UInt8> с длиной в строку
Я рассмотрел много подобных вопросов, но все еще не могу заставить компилятор принять это.
Socket Mobile API (в Objective-C) передает ISktScanDecodedData в метод делегата в Swift (данные могут быть двоичными, поэтому я полагаю, поэтому они не представлены в виде строки):
func onDecodedData(device: DeviceInfo?, DecodedData d: ISktScanDecodedData?) {
let symbology: String = d!.Name()
let rawData: UnsafePointer<UInt8> = d!.getData()
let rawDataSize: UInt32 = decoded!.getDataSize()
// want a String (UTF8 is OK) or Swifty byte array...
}
В C# этот код преобразует необработанные данные в строку:
string s = Marshal.PtrToStringAuto(d.GetData(), d.GetDataSize());
В Swift я могу добраться до UnsafeArray
Но я застрял
let rawArray = UnsafeArray<UInt8>(start: rawData, length: Int(rawDataSize))
В качестве альтернативы я вижу String.fromCString
а также NSString.stringWithCharacters
, но ни один не примет типы аргументов под рукой. Если бы я мог преобразовать из UnsafePointer<UInt8>
в UnsafePointer<()>
например, тогда это будет доступно (хотя я не уверен, будет ли это вообще безопасно):
NSData(bytesNoCopy: UnsafePointer<()>, length: Int, freeWhenDone: Bool)
Есть ли очевидный способ получить строку из всего этого?
2 ответа
Это должно работать:
let data = NSData(bytes: rawData, length: Int(rawDataSize))
let str = String(data: data, encoding: NSUTF8StringEncoding)
Обновление для Swift 3:
let data = Data(bytes: rawData, count: Int(rawDataSize))
let str = String(data: data, encoding: String.Encoding.utf8)
Полученная строка nil
если данные не представляют действительную последовательность UTF-8.
Как насчет этого, "чистый" Swift 2.2 вместо использования NSData:
public extension String {
static func fromCString
(cs: UnsafePointer<CChar>, length: Int!) -> String?
{
if length == .None { // no length given, use \0 standard variant
return String.fromCString(cs)
}
let buflen = length + 1
var buf = UnsafeMutablePointer<CChar>.alloc(buflen)
memcpy(buf, cs, length))
buf[length] = 0 // zero terminate
let s = String.fromCString(buf)
buf.dealloc(buflen)
return s
}
}
и Свифт 3:
public extension String {
static func fromCString
(cs: UnsafePointer<CChar>, length: Int!) -> String?
{
if length == nil { // no length given, use \0 standard variant
return String(cString: cs)
}
let buflen = length + 1
let buf = UnsafeMutablePointer<CChar>.allocate(capacity: buflen)
memcpy(buf, cs, length)
buf[length] = 0 // zero terminate
let s = String(cString: buf)
buf.deallocate(capacity: buflen)
return s
}
}
Правда, немного глупо выделять буфер и копировать данные только для добавления нулевого терминатора.
Очевидно, как упоминал Zaph, вам нужно убедиться, что ваши предположения о кодировке строки будут правильными.