Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
747 views
in Technique[技术] by (71.8m points)

cocoa - SCNGeometryElement setup in Swift 3

I bit the bullet and started converting my app to Swift 3. As always, the converter leaves very much to be desired. In this case, I'm not sure how to properly code the new version. Here is the original:

let indexes : [CInt] = [0,1,2,3]
let dat  = NSData(bytes: indexes, length: sizeofValue(indexes))
let ele = SCNGeometryElement(data:dat, primitiveType: .Triangles, primitiveCount: 2, bytesPerIndex: sizeof(Int))

After running the conversion and writing a new sizeof (thanks), I ended up with this:

let indexes : [CInt] = [0,1,2,3]
let dat  = Data(bytes: UnsafePointer<UInt8>(indexes), count: sizeof(indexes))
let ele = SCNGeometryElement(data:dat, primitiveType: .triangles, primitiveCount: 2, bytesPerIndex: MemoryLayout<Int>.size)

However, this gives me (on the Data(bytes:length:) call):

'init' is unavailable: use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.

I've looked over a few threads here, and read the release notes that cover this, and I'm still baffled what I'm supposed to do here.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You fixed one sizeof but not the other, and you're creating a new pointer where such is unnecessary — any array (given the right element type) can be passed to APIs that take C-style pointers. The direct fix for your code is then:

let indexes: [CInt] = [0,1,2,3]
let dat = Data(bytes: indexes, count: MemoryLayout<CInt>.size * indexes.count)
let ele = SCNGeometryElement(data:dat, primitiveType: .triangles, primitiveCount: 2, bytesPerIndex: MemoryLayout<CInt>.size)

(Note also the fixes to make your MemoryLayouts consistent with the data they describe.)

However, unless you have some need for the extra Data object, for fun with pointers, or for the extra specificity in describing your element, you can use the simpler form:

let indices: [UInt8] = [0,1,2,3] 
let element = SCNGeometryElement(indices: indices, primitiveType: .triangles)

This generic initializer automatically manages memory on the way in, infers the count of the array, and infers the primitiveCount based on the count of the array and the primitiveType you specify.

(Note that an array of four indices is an unusual number for .triangles; either you have one triangle and one unused index, or you actually mean a .triangleStrip containing two primitives.)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...