let buffer: [Int8] = ....
func process(buffer: [UInt8]) { // some code }
将[Int8]缓冲区传递给[Int8]的最佳方法是什么?我知道下面的代码可以工作,但在这种情况下,缓冲区只包含一堆字符,并且不必使用map等函数.
process(buffer.map{ x in UInt8(x) }) // OK process([UInt8](buffer)) // error process(buffer as! [UInt8]) // error
我正在使用Xcode7 b3 Swift2.
解决方法
// first,change your process logic to be generic on any kind of container func process<C: CollectionType where C.Generator.Element == UInt8>(chars: C) { // just to prove it's working... print(String(chars.map { UnicodeScalar($0) })) } // sample input let a: [Int8] = [104,101,108,111] // ascii "Hello" // access the underlying raw buffer as a pointer a.withUnsafeBufferPointer { buf -> Void in process( UnsafeBufferPointer( // cast the underlying pointer to the type you want start: UnsafePointer(buf.baseAddress),count: buf.count)) } // this prints [h,e,l,o]
注意withUnsafeBufferPointer意味着它所说的.这是不安全的,如果你弄错了你可以破坏记忆(尤其要小心计数).它基于您的外部知识工作,例如,如果任何整数是负数,那么您的代码不会介意它们成为损坏的无符号整数.你可能知道,但是Swift类型的系统不能,所以它不会允许它而不诉诸不安全的类型.
也就是说,上述代码是正确的并且在规则范围内,如果您需要性能优势,这些技术是合理的.除非你处理大量的数据或编写一个你称之为无数次的库,否则你几乎肯定不会.
值得注意的是,在某些情况下,数组实际上并未由连续缓冲区支持(例如,如果它是从NSArray强制转换的),在这种情况下,调用.withUnsafeBufferPointer将首先将所有元素复制到连续的数组中.此外,Swift数组是可扩展的,因此底层元素的副本通常随着数组的增长而发生.如果性能绝对至关重要,您可以考虑使用UnsafeMutablePointer分配自己的内存,并使用UnsafeBufferPointer使用固定大小的样式.
对于一个幽默但绝对不在你不应该实际使用的规则示例中,这也将起作用:
process(unsafeBitCast(a,[UInt8].self))
值得注意的是,这些解决方案与a.map {UInt8($0)}不同,因为如果你传递一个负整数,后者将在运行时陷阱.如果有可能,您可能需要先过滤它们.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。