Search code examples
swiftmacoscocoaswift-playground

How can I set a VC as Liveview in Playgrounds?


I'm currently working on a small Playgrounds project (for macOS) and I'm trying to set my own View Controller as the Live View. The following line doesn't work.

PlaygroundPage.current.liveView = ViewController()

When running this, I get the following error.

error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).

I get the same error, when using this:

PlaygroundPage.current.liveView = ViewController(nibName: NSNib.Name("MyView"), bundle: Bundle.main)

Solution

  • Choose File > New > Playground and start with the MacOS Playground template called Single View. This will give you a view in a nib.

    Now modify the code in the playground as follows:

    import AppKit
    import PlaygroundSupport
    
    class ViewController : NSViewController {}
    
    let nibFile = NSNib.Name("MyView")
    var topLevelObjects : NSArray?
    
    Bundle.main.loadNibNamed(nibFile, owner:nil, topLevelObjects: &topLevelObjects)
    let views = (topLevelObjects as! Array<Any>).filter { $0 is NSView }
    
    let vc = ViewController()
    vc.view = views[0] as! NSView
    PlaygroundPage.current.liveView = vc
    

    Run the playground and look in the Assistant Editor pane. You will see this:

    enter image description here


    EDIT It occurs to me that a more pleasant way to write this (placing the decision as to where to get its view in the hands of the view controller itself) would be as follows:

    class ViewController : NSViewController {
        override func loadView() {
            let nibFile = NSNib.Name("MyView")
            var topLevelObjects : NSArray?
            Bundle.main.loadNibNamed(
                nibFile, owner:nil, topLevelObjects: &topLevelObjects)
            let views = (topLevelObjects as! Array<Any>).filter { $0 is NSView }
            self.view = views[0] as! NSView
        }
    }
    PlaygroundPage.current.liveView = ViewController()