Sunday, September 18, 2022

[FIXED] How to print NSValue bytes

Issue

How does one print NSValue bytes? When using print it doesn't print all the bytes and puts '...'. E.g. {length = 128, bytes = 0x00000000 0000f03f 00000000 00000000 ... 00000000 0000f03f }

import Cocoa
import SceneKit

var identityMatrix = SCNMatrix4()

identityMatrix.m11 = 1
identityMatrix.m12 = 0
identityMatrix.m13 = 0
identityMatrix.m14 = 0
identityMatrix.m21 = 0
identityMatrix.m22 = 1
identityMatrix.m23 = 0
identityMatrix.m24 = 0
identityMatrix.m31 = 0
identityMatrix.m32 = 0
identityMatrix.m33 = 1
identityMatrix.m34 = 0
identityMatrix.m41 = 0
identityMatrix.m42 = 0
identityMatrix.m43 = 0
identityMatrix.m44 = 1

var a = [NSValue]()

a.append(NSValue(scnMatrix4:identityMatrix))

identityMatrix.m11 = 1
identityMatrix.m12 = 0
identityMatrix.m13 = 0
identityMatrix.m14 = 0
identityMatrix.m21 = 0
identityMatrix.m22 = 1
identityMatrix.m23 = 0
identityMatrix.m24 = 0
identityMatrix.m31 = 0
identityMatrix.m32 = 0
identityMatrix.m33 = 1
identityMatrix.m34 = 0
identityMatrix.m41 = 0
identityMatrix.m42 = -1.0
identityMatrix.m43 = 0
identityMatrix.m44 = 1

a.append(NSValue(scnMatrix4:identityMatrix))

print(a[0])

Solution

First of all, we can tidy this up by using an array literal, and the SCNMatrix4 initializer to get rid of all the mutability:

import Cocoa
import SceneKit

let a = [
    SCNMatrix4(
        m11: 1, m12: 0, m13: 0, m14: 0,
        m21: 0, m22: 0, m23: 0, m24: 0,
        m31: 0, m32: 0, m33: 1, m34: 0,
        m41: 0, m42: 0, m43: 0, m44: 1
    ),
    SCNMatrix4(
        m11: 1, m12:  0, m13: 0, m14: 0,
        m21: 0, m22:  1, m23: 0, m24: 0,
        m31: 0, m32:  0, m33: 1, m34: 0,
        m41: 0, m42: -1, m43: 0, m44: 1
    ),
].map(NSValue.init(scnMatrix4:))

print(a[0])

That makes the code much more sensible. We can also notice from the documentation that there's already a constant that we can use to get an identity matrix:

import Cocoa
import SceneKit

let a = [
    SCNMatrix4Identity,
    SCNMatrix4(
        m11: 1, m12:  0, m13: 0, m14: 0,
        m21: 0, m22:  1, m23: 0, m24: 0,
        m31: 0, m32:  0, m33: 1, m34: 0,
        m41: 0, m42: -1, m43: 0, m44: 1
    ),
].map(NSValue.init(scnMatrix4:))

print(a[0])

It's not clear why these matrices are wrapped in NSValue, but to display details about them (and call other methods on them), you'll need to fish the matrix back out of the NSValue box using the scnMatrix4Value API:

let sampleMatrix = a[0].scnMatrix4Value
print(sampleMatrix)

If you want to print the byte layout of these, (although it's still really not clear why you would want this, since AFAICT, NSValue and SCNMatrix4 make no promises about their memory layout), you can use the usual pointer APIs, in combination with some hex printing logic such as this:

withUnsafeBytes(of: &sampleMatrix) { sampleMatrixPointer in
    print(sampleMatrixPointer.map { String(format: "%02x", $0) }.joined(separator: ""))
}

prints:

000000000000f03f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f03f0000000000000000000000000000000000000000000000000000000000000000000000000000f03f


Answered By - Alexander
Answer Checked By - Katrina (PHPFixing Volunteer)

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.