Build SF Symbols Browser in 3D Using SceneKit and SwiftUI | by Mark Lucking | Aug, 2022

A stab at recreating the symbols browser presented @ the WWDC2021

1*gQV86hr5lucZwV9LW XcIQ
Code from the WWDC2021 presentation on SF Symbols

In WWDC2022, Apple announced that it had expanded the SF Symbols library. A library that it launched alongside the SwiftUI framework in 2019. A library with some 4000+ symbols now, it seems. Symbols that they had previewed with a very sexy-looking interface in WWDC2021.

1*qskVVR4Surgw Bx7 nrmkA
An animated GIF of the new SF Symbols available in iOS 15

I loved the idea of a rolling menu on the face of a ball of sorts and decided to try to rebuild it myself.

The Journey

I made two attempts to build this — the first using the Core Image framework and SwiftUI interface, an endeavor to reverse engineer Apple’s Codette shown. The second using SceneKit — this paper is about the second attempt — the first failed.

SceneKit framework

Bon, now, although you can do some fascinating stuff with SwiftUI these days in 3D, see this paper and this one, too — as I just mentioned, it wasn’t the route I would ultimately take. After the false start, I began with the code I wrote in this article as a base.

SceneKit basic template

Note the SceneKitScene is simply an empty *.scn file I created using Xcode. It does nothing more than present a white globe as the basis for our menu.


Of course, I needed far more than a simple globe; I needed a globe in which I could add multiple individual touchable surfaces.

1*J5unsRbUWdQZ4 3t7fiK7w

The diamonds you see flanking the edge of this globe are individual four-sided cylinders that I added and then rotated around the center of the globe. Sure, you’re right. The diamonds need to cover more of the globe; they will, in time, stay with me.

To plot the positions of said diamonds, I used the formulae I described in these papers, namely sin, and cos. That said, figuring out the plates’ angles to rotate around wasn’t simple.

Note the angles shown are in radians; I used radians because that is the value the simdEularAngles uses; they represent either 0, 45, or 90 degrees. I worked out the angles needed for the other plates I intended to add, and with this the net result.

1*rJ13myf YNBvbOUO36h3fQ

I colored the different plates depending on which axis I plotted them on. I also considered trying to fit five plates on the tropic of Capricorn and the Tropic of Cancer, but I decided to try to keep things simple.


Having created my football as it now looked, I needed to add some gestures and some values so that I could identify which plate was being swiped. I copied and pasted an extension to SCNNode from the previous article I had already used.

@objc func handleTap(_ gestureRecognize: UIGestureRecognizer) {
let p = gestureRecognize.location(in: view)
let hitResults = view.hitTest(p, options: [:])
if hitResults.count > 0 {
let result = hitResults[0].node as? NewNode
if (result != nil) {
print("proxy ",result?.proxy?.x,result?.proxy?.y,result?.proxy?.z)

I added a simple gesture recogniser to the view with these two lines.

let tapRecognizer = UITapGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.handleTap(_:)))view.addGestureRecognizer(tapRecognizer)

I ran it; it worked well. I could tap the different plates and identify which one was which as I did so.

I added a swipe gesture and turned off the camera control to test it.

As you see, I could now move the ball by using a swipe up, down, left or right — but only if I did so by touching the background. At this point, I created a symbol browser; sure, it contains just a single symbol — but you get the picture.

News Credit

%d bloggers like this: