Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I address the “There was a problem running this page” message in Swift Playgrounds?

I am trying to make something with SceneKit for the WWDC Student Challenge, which requires my project be in a Swift playground. I keep getting the message that says “There was a problem running this page.” It offers no error messages. It just suggests that check my code or start over. I have tried removing pieces of code individually, but I cannot locate the source of this issue. I have also tried running it in man Xcode playground, which offered the warning of, and I quote, “The playground could not continue running because the playground source did”. I am stuck. What is wrong with my code.

import UIKit
import SceneKit
import QuartzCore 
import PlaygroundSupport

class GameScene: UIViewController, SCNSceneRendererDelegate {
    var primaryView: SCNView!
    var primaryScene: SCNScene!
    var cameraNode: SCNNode!
    
    override func viewDidLoad() {
        sceneAndViewInit()
        cameraInit()
        createGround()
        moonInit()
    }
    
    func createGround() {
        var ground = SCNBox(width: 200, height: 1, length: 200, chamferRadius: 0)
        var groundPhysicsShape = SCNPhysicsShape(geometry: ground, options: nil) 
        var groundNode = SCNNode(geometry: ground)
        ground.firstMaterial?.diffuse.contents = UIColor.orange
        ground.firstMaterial?.specular.contents = UIColor.white
        groundNode.position = SCNVector3(0, -6, 0)
        groundNode.physicsBody = SCNPhysicsBody(type: .static, shape: groundPhysicsShape)
        primaryScene.rootNode.addChildNode(groundNode)
    }
    
    func sceneAndViewInit() {
        primaryView = SCNView(frame: CGRect(x: 0, y: 0, width: 500, height: 300))
        primaryView.allowsCameraControl = true
        primaryView.autoenablesDefaultLighting = true
        
        primaryScene = SCNScene()
        
        primaryView.scene = primaryScene
        primaryView.isPlaying = true
    }
    
    func cameraInit() {
        var cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 2)
        cameraNode.camera?.fieldOfView = 65
        cameraNode.camera?.wantsHDR = false
        primaryScene.rootNode.addChildNode(cameraNode)
    }
    
    func moonInit() {
        let moonScene = SCNScene(named: "Moon.scn")
        var moonNode = moonScene?.rootNode.childNode(withName: "Sphere", recursively: true)
        var moonPhysicsShape = SCNPhysicsShape(node: moonNode!, options: nil)
        moonNode?.position = SCNVector3(0, 0, 0)
        moonNode?.scale = SCNVector3(1, 1, 1)
        moonNode?.name = "Moon"
        moonNode?.physicsBody = SCNPhysicsBody(type: .static, shape: moonPhysicsShape)
        primaryScene.rootNode.addChildNode(moonNode!)
    }
    
    func renderer(_ aRenderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
        print(time)
    }
}

let gameScene = GameScene()
PlaygroundPage.current.liveView = gameScene

(“Moon.scn” is a file that I have in the resources/files section along with its texture, and I still have the issue without any of the moon related code.)

like image 974
42nd Avatar asked May 13 '20 21:05

42nd


People also ask

How long does it take to complete Swift Playgrounds?

Swift Fundamentals – Pluralsight As an aspiring app developer, you'll learn how Swift works with data and Swift playgrounds. You'll also adopt a protocol-oriented programming mindset as you work on developing apps on iPhone, Mac, or iPad. It takes about three to four learning hours to complete this course.

Is Swift Playgrounds 4 out?

Swift Playgrounds 4 now available.

Is Swift Playgrounds a good way to learn to code?

Swift Playgrounds is a beautiful looking environment to learn to code. It's a nice, modern, object-oriented language and I can learn concepts and conventions and put them to work later in Xcode. Children can choose step-by-step lessons and puzzles to build their coding knowledge and skills.


2 Answers

To view the full error message, go to Settings app -> Playgrounds -> turn on Authoring Debug Mode. This doesn't directly solve the issue but it's a lot more helpful for locating errors.

Settings app -> Playgrounds -> turn on Authoring Debug Mode

like image 59
jp21 Avatar answered Oct 27 '22 06:10

jp21


I have found a way to address this issue. However, I can only offer you a round-ish idea of what the issue is and how to fix it.
The problem seems to be with the variable declarations at the top of the class.

var primaryView: SCNView!
var primaryScene: SCNScene!
var cameraNode: SCNNode!

The exclamation mark following the type indicates that the variable is an implicitly-unwrapped optional (I am quoting from this Stack Overflow response that explains what this is in more depth), but more-or-less the variable will automatically force unwrap whenever it is used. I have a more of a working knowledge of Swift than a technical one, so my guess is that when a GameScene object is created a synthetic initializer tries to set up these variables, it, for some reason, needs to read from the variables, gets nil, and cannot continue.

The solution appears to be putting the values of the variables in their initial declaration (There might be a better solution, but this at least works in my testing.), so that they are not nil for the initializer. Now the reason that I cannot fully explain the issue here is that this only seems to be necessary for the SCNScene variable. I don't really know why this is the case.

Code (*** mark important comments):

import UIKit
import SceneKit
import QuartzCore 
import PlaygroundSupport

class GameScene: UIViewController, SCNSceneRendererDelegate {
    var primaryView: SCNView!// = SCNView(frame: CGRect(x: 0, y: 0, width: 500, height: 300)) //***This seems to work for reasons beyond me with the implicitly-unwrapped optional***
    var primaryScene = SCNScene() //***The implicitly unwrapped optional is removed here***
    var cameraNode = SCNNode() //***The implicitly unwrapped optional is removed here (I am not sure if that is necessary but it probably good practice not to use it anywhere intros code.  I use it earlier to demonstrate its weird complexities.)***
    
    override func viewDidLoad() {
        sceneAndViewInit()
        cameraInit()
        createGround()
        //moonInit() ***I removed this for simplicity in the answer***
    }
    
    func createGround() {
        var ground = SCNBox(width: 200, height: 1, length: 200, chamferRadius: 0)
        var groundPhysicsShape = SCNPhysicsShape(geometry: ground, options: nil) 
        var groundNode = SCNNode(geometry: ground)
        ground.firstMaterial?.diffuse.contents = UIColor.orange
        ground.firstMaterial?.specular.contents = UIColor.white
        groundNode.position = SCNVector3(0, -6, 0)
        groundNode.physicsBody = SCNPhysicsBody(type: .static, shape: groundPhysicsShape)
        primaryScene.rootNode.addChildNode(groundNode)
    }
    
    func sceneAndViewInit() {
        primaryView = SCNView(frame: CGRect(x: 0, y: 0, width: 500, height: 300))
        primaryView.allowsCameraControl = true
        primaryView.autoenablesDefaultLighting = true
        
        //primaryScene = SCNScene() ***This is not necessary when it is declared above***
        
        self.primaryView.scene = primaryScene
        //primaryView.isPlaying = true
        
        self.view = primaryView //***I realized later you need this bit of code or the program will only display a blank screen***
    }
    
    func cameraInit() {
        //var cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 2)
        cameraNode.camera?.fieldOfView = 65
        cameraNode.camera?.wantsHDR = false
        primaryScene.rootNode.addChildNode(cameraNode)
    }
    
    func moonInit() {
        let moonScene = SCNScene(named: "Moon.scn")
        var moonNode = moonScene?.rootNode.childNode(withName: "Sphere", recursively: true)
        var moonPhysicsShape = SCNPhysicsShape(node: moonNode!, options: nil)
        moonNode?.position = SCNVector3(0, 0, 0)
        moonNode?.scale = SCNVector3(1, 1, 1)
        moonNode?.name = "Moon"
        moonNode?.physicsBody = SCNPhysicsBody(type: .static, shape: moonPhysicsShape)
        primaryScene.rootNode.addChildNode(moonNode!)
    }
    
    func renderer(_ aRenderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
        print(time)
    }
}

let gameScene = GameScene()
PlaygroundPage.current.liveView = gameScene

One final note: The self.view = primaryView code is really important. I make a note about in the full code, but I have found this way too hard to locate on the internet. I think this has to do with UIViewController (I don't know much about UIKit at all.), but either SceneKit or UIKit just displays a blank screen if you do now have that bit of code. If you don't figure out that these are separate issues they are really hard to decipher.

like image 1
42nd Avatar answered Oct 27 '22 06:10

42nd