Scene Editor Development: Showing a SwiftUI View Based on a Selection

The inspector for the scene editor has separate SwiftUI views for each kind of item in a SpriteKit scene. There’s a sprite inspector for sprites, a label inspector for labels, and so on.

When someone selects an item from the scene graph, the inspector should show the correct view. If someone selects a sprite, the inspector view should show the sprite inspector. How do you show the correct view based on the selection?

My solution is to get the class name for the selected item, add a switch statement to the view body, and show the correct view based on the class name.

Getting the Class Name

The inspector has a property that contains the selected item from the scene graph.

@State var node: SKNode

Because each kind of item in a SpriteKit scene has its own class, I can get the name of the class for the node property and show the correct view based on the name of the class.

NSObject is the base class for every SpriteKit class. The NSObject class has a nameOfClass property for Mac, but not iOS. But I saw on Stack Overflow that you can add an extension to NSObject to get the name of the class on iOS.

public extension NSObject {
  class var nameOfClass: String {
    return NSStringFromClass(self).components(separatedBy: ".").last!
  }
    
  var nameOfClass: String {
    return NSStringFromClass(type(of: self)).components(separatedBy: ".").last!
  }
}

Adding a Switch Statement to the SwiftUI View

Now that I can get the names of the SpriteKit classes, I can add a switch statement in the SwiftUI view body and show the correct view based on the class of the selected item in the scene graph.

struct Inspector: View {
  @State var node: SKNode
        
  var body: some View {
    switch node.nameOfClass {
    case "SKSpriteNode":
      SpriteInspector(node: node as! SKSpriteNode)
    case "SKLabelNode":
      LabelInspector(node: node as! SKLabelNode)
    case "SKLightNode":
      LightInspector(node: node as! SKLightNode)
    // Other SpriteKit classes go here.
    default:
      EmptyView()
    }
  }
}

I can safely cast with as! because I know the class of the selected item.

Get the Swift Dev Journal Newsletter

Subscribe and get exclusive articles, a free guide on moving from tutorials to making your first app, notices of sales on books, and anything I decide to add in the future.

    We won't send you spam. Unsubscribe at any time.